[banshee] [JavaScriptCore] Implemented CallAsConstructor
- From: Aaron Bockover <abock src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [banshee] [JavaScriptCore] Implemented CallAsConstructor
- Date: Tue, 30 Nov 2010 17:02:05 +0000 (UTC)
commit a9c021eda7bca8a5970db03ed6dc2657b544fb35
Author: Aaron Bockover <abockover novell com>
Date: Tue Nov 30 11:50:41 2010 -0500
[JavaScriptCore] Implemented CallAsConstructor
Fixed crasher in JSClassDefinition static method invocation because
the delegate invoked by native was being GCed.
.../JavaScriptCore.Bridge/Tests/RuntimeTests.cs | 4 +-
.../JavaScriptCore/JSClassDefinition.cs | 51 ++++++++++++++------
.../Banshee.WebBrowser/JavaScriptCore/JSObject.cs | 11 ++++
.../Banshee.WebBrowser/JavaScriptCore/JSValue.cs | 9 ++++
.../JavaScriptCore/Tests/JSClassTests.cs | 25 +++++++---
5 files changed, 75 insertions(+), 25 deletions(-)
---
diff --git a/src/Core/Banshee.WebBrowser/JavaScriptCore.Bridge/Tests/RuntimeTests.cs b/src/Core/Banshee.WebBrowser/JavaScriptCore.Bridge/Tests/RuntimeTests.cs
index 1ac4ca7..f73e545 100644
--- a/src/Core/Banshee.WebBrowser/JavaScriptCore.Bridge/Tests/RuntimeTests.cs
+++ b/src/Core/Banshee.WebBrowser/JavaScriptCore.Bridge/Tests/RuntimeTests.cs
@@ -48,7 +48,7 @@ namespace JavaScriptCore.Bridge.Tests
[Test]
public void TestExceptionBoundaryJsCatch ()
{
- context.EvaluateScript ("try { mjsc.import = 'foo'; } catch (e) { this.p = e.toString (); }");
+ context.EvaluateScript ("try { mjs.import = 'foo'; } catch (e) { this.p = e.toString (); }");
Assert.AreEqual ("IllegalOperationError: Setting properties on this object is not allowed",
context.GlobalObject.GetProperty ("p").StringValue);
}
@@ -57,7 +57,7 @@ namespace JavaScriptCore.Bridge.Tests
public void TestExceptionBoundaryRoundTrip ()
{
try {
- context.EvaluateScript ("mjsc.import = 'foo'");
+ context.EvaluateScript ("mjs.import = 'foo'");
} catch (JSException e) {
Assert.AreEqual ("IllegalOperationError: Setting properties on this object is not allowed",
e.Error.StringValue);
diff --git a/src/Core/Banshee.WebBrowser/JavaScriptCore/JSClassDefinition.cs b/src/Core/Banshee.WebBrowser/JavaScriptCore/JSClassDefinition.cs
index a7f48d2..3308639 100644
--- a/src/Core/Banshee.WebBrowser/JavaScriptCore/JSClassDefinition.cs
+++ b/src/Core/Banshee.WebBrowser/JavaScriptCore/JSClassDefinition.cs
@@ -59,6 +59,7 @@ namespace JavaScriptCore
private JSClassDefinitionNative raw;
private Dictionary<string, MethodInfo> static_methods;
+ private JSObject.CallAsFunctionCallback static_function_callback;
public virtual string ClassName {
get { return GetType ().FullName.Replace (".", "_"); }
@@ -82,6 +83,7 @@ namespace JavaScriptCore
Override ("OnJSSetProperty", () => raw.set_property = new JSObject.SetPropertyCallback (JSSetProperty));
Override ("OnJSDeleteProperty", () => raw.delete_property = new JSObject.DeletePropertyCallback (JSDeleteProperty));
Override ("OnJSGetPropertyNames", () => raw.get_property_names = new JSObject.GetPropertyNamesCallback (JSGetPropertyNames));
+ Override ("OnCallAsConstructor", () => raw.call_as_constructor = new JSObject.CallAsConstructorCallback (JSCallAsConstructor));
}
private void InstallStaticMethods ()
@@ -116,10 +118,14 @@ namespace JavaScriptCore
methods = new List<JSStaticFunction> ();
}
+ if (static_function_callback == null) {
+ static_function_callback = new JSObject.CallAsFunctionCallback (OnStaticFunctionCallback);
+ }
+
methods.Add (new JSStaticFunction () {
Name = attr.Name,
Attributes = attr.Attributes,
- Callback = OnStaticFunctionCallback
+ Callback = static_function_callback
});
}
}
@@ -128,17 +134,11 @@ namespace JavaScriptCore
var size = Marshal.SizeOf (typeof (JSStaticFunction));
var ptr = Marshal.AllocHGlobal (size * (methods.Count + 1));
- Console.WriteLine ("ALLOC {0} bytes ({1}b x {2}) @ {3}",
- size * (methods.Count + 1), size, methods.Count + 1, ptr);
-
for (int i = 0; i < methods.Count; i++) {
- Console.WriteLine ("STRUCT [{0}] @ {1}",
- methods[i].Name, new IntPtr (ptr.ToInt64 () + size * i));
Marshal.StructureToPtr (methods[i],
new IntPtr (ptr.ToInt64 () + size * i), false);
}
- Console.WriteLine ("EMPTY @ {0}", new IntPtr (ptr.ToInt64 () + size * methods.Count));
Marshal.StructureToPtr (new JSStaticFunction (),
new IntPtr (ptr.ToInt64 () + size * methods.Count), false);
@@ -167,19 +167,25 @@ namespace JavaScriptCore
{
var context = new JSContext (ctx);
var fn = new JSObject (ctx, function);
+ string fn_name = null;
+ if (fn.HasProperty ("name")) {
+ var prop = fn.GetProperty ("name");
+ if (prop != null && prop.IsString) {
+ fn_name = prop.StringValue;
+ }
+ }
MethodInfo method = null;
- if (!static_methods.TryGetValue (fn.GetProperty ("name").StringValue, out method)) {
- return IntPtr.Zero;
+ if (fn_name == null || !static_methods.TryGetValue (fn_name, out method)) {
+ return JSValue.NewUndefined (context).Raw;
}
- var args = new JSValue[argumentCount.ToInt32 ()];
-
- for (int i = 0; i < args.Length; i++) {
- args[i] = new JSValue (context, Marshal.ReadIntPtr (arguments, i * IntPtr.Size));
- }
+ var result = method.Invoke (null, new object [] {
+ fn,
+ new JSObject (context, thisObject),
+ JSValue.MarshalArray (ctx, arguments, argumentCount)
+ });
- var result = method.Invoke (null, new object [] { fn, new JSObject (context, thisObject), args });
return result == null
? JSValue.NewUndefined (context).Raw
: ((JSValue)result).Raw;
@@ -260,5 +266,20 @@ namespace JavaScriptCore
protected virtual void OnJSGetPropertyNames (JSObject obj, JSPropertyNameAccumulator propertyNames)
{
}
+
+ private IntPtr JSCallAsConstructor (IntPtr ctx, IntPtr constructor,
+ IntPtr argumentCount, IntPtr arguments, ref IntPtr exception)
+ {
+ var result = OnJSCallAsConstructor (new JSObject (ctx, constructor),
+ JSValue.MarshalArray (ctx, arguments, argumentCount));
+ return result == null
+ ? JSValue.NewUndefined (new JSContext (ctx)).Raw
+ : ((JSValue)result).Raw;
+ }
+
+ protected virtual JSObject OnJSCallAsConstructor (JSObject constructor, JSValue [] args)
+ {
+ return null;
+ }
}
}
diff --git a/src/Core/Banshee.WebBrowser/JavaScriptCore/JSObject.cs b/src/Core/Banshee.WebBrowser/JavaScriptCore/JSObject.cs
index c9ede2a..91bb0c9 100644
--- a/src/Core/Banshee.WebBrowser/JavaScriptCore/JSObject.cs
+++ b/src/Core/Banshee.WebBrowser/JavaScriptCore/JSObject.cs
@@ -181,6 +181,17 @@ namespace JavaScriptCore
#endregion
[DllImport (JSContext.NATIVE_IMPORT)]
+ private static extern void JSObjectSetPrivate (IntPtr obj, IntPtr data);
+
+ [DllImport (JSContext.NATIVE_IMPORT)]
+ private static extern IntPtr JSObjectGetPrivate (IntPtr obj);
+
+ public IntPtr UnmanagedPrivate {
+ get { return JSObjectGetPrivate (Raw); }
+ set { JSObjectSetPrivate (Raw, value); }
+ }
+
+ [DllImport (JSContext.NATIVE_IMPORT)]
private static extern bool JSObjectIsFunction (IntPtr ctx, IntPtr obj);
public bool IsFunction {
diff --git a/src/Core/Banshee.WebBrowser/JavaScriptCore/JSValue.cs b/src/Core/Banshee.WebBrowser/JavaScriptCore/JSValue.cs
index ae14e57..5614b1c 100644
--- a/src/Core/Banshee.WebBrowser/JavaScriptCore/JSValue.cs
+++ b/src/Core/Banshee.WebBrowser/JavaScriptCore/JSValue.cs
@@ -277,5 +277,14 @@ namespace JavaScriptCore
{
return IsObject ? ToJsonString (0) ?? StringValue : StringValue;
}
+
+ public static JSValue [] MarshalArray (IntPtr context, IntPtr items, IntPtr itemCount)
+ {
+ var array = new JSValue[itemCount.ToInt32 ()];
+ for (int i = 0; i < array.Length; i++) {
+ array[i] = new JSValue (context, Marshal.ReadIntPtr (items, i * IntPtr.Size));
+ }
+ return array;
+ }
}
}
diff --git a/src/Core/Banshee.WebBrowser/JavaScriptCore/Tests/JSClassTests.cs b/src/Core/Banshee.WebBrowser/JavaScriptCore/Tests/JSClassTests.cs
index f460e53..df399ba 100644
--- a/src/Core/Banshee.WebBrowser/JavaScriptCore/Tests/JSClassTests.cs
+++ b/src/Core/Banshee.WebBrowser/JavaScriptCore/Tests/JSClassTests.cs
@@ -36,7 +36,14 @@ namespace JavaScriptCore.Tests
{
private JSContext context;
- private class JSClassTest : JSClassDefinition
+ [TestFixtureSetUp]
+ public void Init ()
+ {
+ context = new JSContext ();
+ context.GlobalObject.SetProperty ("x", new JSObject (context, new JSTestStaticClass ().CreateClass ()));
+ }
+
+ private class JSTestStaticClass : JSClassDefinition
{
[JSStaticFunction ("return_managed_null")]
private static JSValue ReturnManagedNull (JSObject function, JSObject thisObject, JSValue [] args)
@@ -96,13 +103,6 @@ namespace JavaScriptCore.Tests
}
}
- [TestFixtureSetUp]
- public void Init ()
- {
- context = new JSContext ();
- context.GlobalObject.SetProperty ("x", new JSObject (context, new JSClassTest ().CreateClass ()));
- }
-
[Test]
public void TestEnsureJavaScriptCoreVoidReturnIsUndefined ()
{
@@ -150,6 +150,15 @@ namespace JavaScriptCore.Tests
{
context.EvaluateScript ("x.args (true, 42, 'banshee', x.args, null, undefined)");
}
+
+ private class JSTestInstanceClass : JSClassDefinition
+ {
+ protected override JSObject OnJSCallAsConstructor (JSObject constructor, JSValue[] args)
+ {
+ Console.WriteLine ("HELLO!");
+ return null;
+ }
+ }
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]