Index: Source/bindings/core/dart/DartJsInterop.cpp |
diff --git a/Source/bindings/core/dart/DartJsInterop.cpp b/Source/bindings/core/dart/DartJsInterop.cpp |
index 76ba5ddfe7e7a02b887455b211cd392565c1e14b..4afe555d642e06a1da77065ccd5bf18c0dba5f38 100644 |
--- a/Source/bindings/core/dart/DartJsInterop.cpp |
+++ b/Source/bindings/core/dart/DartJsInterop.cpp |
@@ -147,6 +147,7 @@ const char* dartArrayPolyfill = |
"})();"; |
static v8::Local<v8::FunctionTemplate> dartFunctionTemplate(); |
+static v8::Local<v8::FunctionTemplate> dartFunctionTemplateNoWrap(); |
static v8::Local<v8::FunctionTemplate> dartObjectTemplate(); |
static v8::Local<v8::FunctionTemplate> dartListTemplate(); |
@@ -190,18 +191,43 @@ static void functionInvocationCallback(const v8::FunctionCallbackInfo<v8::Value> |
// there are 2 arguments, the first argument is "this" and the second |
// argument is an array of arguments. |
if (args.Length() > 1) { |
- dartFunctionArgs.append(JsInterop::toDart(args[0])); |
+ dartFunctionArgs.append(JsInterop::toDart(args[0], true)); |
} |
v8::Local<v8::Array> argsList = args[args.Length()-1].As<v8::Array>(); |
uint32_t argsListLength = argsList->Length(); |
for (uint32_t i = 0; i < argsListLength; i++) { |
- dartFunctionArgs.append(JsInterop::toDart(argsList->Get(i))); |
+ dartFunctionArgs.append(JsInterop::toDart(argsList->Get(i), true)); |
} |
setJsReturnValue(domData, args, Dart_InvokeClosure(handle, dartFunctionArgs.size(), dartFunctionArgs.data())); |
} |
+static void functionInvocationCallbackNoWrap(const v8::FunctionCallbackInfo<v8::Value>& args) |
+{ |
+ DartScopes scopes(args.Holder()); |
+ Dart_Handle handle = scopes.handle; |
+ DartDOMData* domData = DartDOMData::current(); |
+ ASSERT(domData); |
+ ASSERT(DartUtilities::isFunction(domData, handle)); |
+ |
+ Vector<Dart_Handle> dartFunctionArgs; |
+ ASSERT(args.Length() == 1 || args.Length() == 2); |
+ // If there is 1 argument, we assume it is a v8:Array or arguments, if |
+ // there are 2 arguments, the first argument is "this" and the second |
+ // argument is an array of arguments. |
+ if (args.Length() > 1) { |
+ dartFunctionArgs.append(JsInterop::toDart(args[0], false)); |
+ } |
+ |
+ v8::Local<v8::Array> argsList = args[args.Length()-1].As<v8::Array>(); |
+ uint32_t argsListLength = argsList->Length(); |
+ for (uint32_t i = 0; i < argsListLength; i++) { |
+ dartFunctionArgs.append(JsInterop::toDart(argsList->Get(i), false)); |
+ } |
+ |
+ setJsReturnValue(domData, args, Dart_InvokeClosure(handle, dartFunctionArgs.size(), dartFunctionArgs.data())); |
+} |
static v8::Local<v8::ObjectTemplate> setupInstanceTemplate(v8::Local<v8::FunctionTemplate> proxyTemplate) |
{ |
v8::Local<v8::ObjectTemplate> instanceTemplate = proxyTemplate->InstanceTemplate(); |
@@ -209,6 +235,7 @@ static v8::Local<v8::ObjectTemplate> setupInstanceTemplate(v8::Local<v8::Functio |
return instanceTemplate; |
} |
+ |
static v8::Local<v8::FunctionTemplate> dartFunctionTemplate() |
{ |
DEFINE_STATIC_LOCAL(v8::Persistent<v8::FunctionTemplate>, proxyTemplate, ()); |
@@ -226,16 +253,17 @@ static v8::Local<v8::FunctionTemplate> dartFunctionTemplate() |
return proxyTemplateLocal; |
} |
-static v8::Local<v8::FunctionTemplate> dartObjectTemplate() |
+static v8::Local<v8::FunctionTemplate> dartFunctionTemplateNoWrap() |
{ |
DEFINE_STATIC_LOCAL(v8::Persistent<v8::FunctionTemplate>, proxyTemplate, ()); |
v8::Local<v8::FunctionTemplate> proxyTemplateLocal; |
v8::Isolate* v8Isolate = v8::Isolate::GetCurrent(); |
if (proxyTemplate.IsEmpty()) { |
- proxyTemplate.Reset(v8Isolate, v8::FunctionTemplate::New(v8Isolate)); |
+ proxyTemplate.Reset(v8::Isolate::GetCurrent(), v8::FunctionTemplate::New(v8Isolate)); |
proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, proxyTemplate); |
- proxyTemplateLocal->SetClassName(v8::String::NewFromUtf8(v8Isolate, "DartObject")); |
- setupInstanceTemplate(proxyTemplateLocal); |
+ v8::Local<v8::ObjectTemplate> instanceTemplate = setupInstanceTemplate(proxyTemplateLocal); |
+ |
+ instanceTemplate->SetCallAsFunctionHandler(&functionInvocationCallbackNoWrap); |
} else { |
proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, proxyTemplate); |
} |
@@ -291,7 +319,7 @@ public: |
void setReturnValue(v8::Local<v8::Value> ret) |
{ |
ASSERT(!tryCatch.HasCaught()); |
- Dart_SetReturnValue(args, JsInterop::toDart(ret)); |
+ Dart_SetReturnValue(args, JsInterop::toDart(ret, false)); |
ASSERT(!tryCatch.HasCaught()); |
} |
@@ -312,17 +340,19 @@ v8::Local<v8::Value> JsInterop::fromDart(DartDOMData* domData, Dart_Handle handl |
v8::Handle<v8::Value> value = V8Converter::toV8IfPrimitive(domData, handle, exception); |
if (!value.IsEmpty() || exception) |
return value; |
- // TODO(terry): START of uncommented block by Jacob, I've re-enabled for clamped arrays... |
- value = V8Converter::toV8IfBrowserNative(domData, handle, exception); |
- if (!value.IsEmpty() || exception) |
- return value; |
- // TODO(terry): END of uncommented block by Jacob. |
- if (DartDOMWrapper::subtypeOf(handle, JsObject::dartClassId)) { |
- JsObject* object = DartDOMWrapper::unwrapDartWrapper<JsObject>(domData, handle, exception); |
+ |
+ Dart_Handle jso = invokeTopLevelJsInteropMethod(domData, "unwrap_jso", 1, &handle); |
+ ASSERT(!Dart_IsError(jso)); |
+ if (DartDOMWrapper::subtypeOf(jso, JsObject::dartClassId)) { |
+ JsObject* object = DartDOMWrapper::unwrapDartWrapper<JsObject>(domData, jso, exception); |
if (exception) |
return v8::Local<v8::Value>(); |
return object->localV8Object(); |
} |
+ // TODO(terry): START of uncommented block by Jacob, I've re-enabled for clamped arrays... |
+ value = V8Converter::toV8IfBrowserNative(domData, handle, exception); |
+ if (!value.IsEmpty() || exception) |
+ return value; |
if (DartUtilities::isFunction(domData, handle)) { |
v8::Local<v8::Object> functionProxy = dartFunctionTemplate()->InstanceTemplate()->NewInstance(); |
@@ -395,7 +425,7 @@ v8::Local<v8::Object> JsObject::localV8Object() |
return v8::Local<v8::Object>::New(v8::Isolate::GetCurrent(), v8Object); |
} |
-Dart_Handle JsInterop::toDart(v8::Local<v8::Value> v8Handle) |
+Dart_Handle JsInterop::toDart(v8::Local<v8::Value> v8Handle, bool sometimesUseHtml) |
{ |
Dart_Handle handle = V8Converter::toDartIfPrimitive(v8Handle); |
if (handle) |
@@ -426,27 +456,117 @@ Dart_Handle JsInterop::toDart(v8::Local<v8::Value> v8Handle) |
} |
} |
- return JsObject::toDart(object); |
+ return JsObject::toDart(object, sometimesUseHtml); |
} |
-Dart_Handle JsObject::toDart(v8::Local<v8::Object> object) |
+Dart_Handle JsObject::toDart(v8::Local<v8::Object> object, bool sometimesUseHtml) |
{ |
- // FIXME: perform caching so that === can be used. |
+ Dart_Handle wrapper; |
+ v8::Isolate* v8Isolate = v8::Isolate::GetCurrent(); |
+ DartDOMData* domData = DartDOMData::current(); |
+ DartJsInteropData* interopData = domData->jsInteropData(); |
+ v8::Local<v8::String> existingDartWrapperKey = interopData->existingDartWrapperHiddenField(v8Isolate); |
+ |
+ // TODO(alanknight): This will fail for multiple isolates referencing the same JS object. |
+ // We probably need to use a different property name for different isolates. |
+ v8::Local<v8::Value> hiddenValue = object->GetHiddenValue(existingDartWrapperKey); |
+ |
+ if (*hiddenValue && hiddenValue->IsObject()) { |
+ DartPersistentValue* scriptValue = DartHandleProxy::readPointerFromProxy(hiddenValue.As<v8::Object>()); |
+ ASSERT(scriptValue->isIsolateAlive()); |
+ // If the isolate does not match we fall back to using the existing JS |
+ // wrapper for the Dart object so that simple cases that would work in |
+ // Dart2Js work. We could alternately throw an exception here. |
+ if (scriptValue->isolate() == Dart_CurrentIsolate()) { |
+ Dart_Handle wrapper = scriptValue->value(); |
+ if (sometimesUseHtml) { |
+ wrapper = invokeTopLevelJsInteropMethod(domData, "_maybeWrap", 1, &wrapper); |
+ } |
+ return wrapper; |
+ } |
+ } |
+ |
+ Dart_Handle ret = 0; |
if (object->IsFunction()) { |
RefPtr<JsFunction> jsFunction = JsFunction::create(object.As<v8::Function>()); |
- return JsFunction::toDart(jsFunction); |
+ wrapper = JsFunction::toDart(jsFunction); |
+ } else if (object->IsArray() |
+ // Check for Dart List objects from different Dart isolates. |
+ // In dart2js the List from a different isolate would just be a regular |
+ // JS Array so it can be treated as a JS Array. |
+ || dartListTemplate()->HasInstance(object)) { |
+ RefPtr<JsArray> jsArray = JsArray::create(object); |
+ wrapper = JsArray::toDart(jsArray); |
+ } else { |
+ RefPtr<JsObject> jsObject = JsObject::create(object); |
+ wrapper = JsObject::toDart(jsObject); |
+ if (sometimesUseHtml) { |
+ ret = invokeTopLevelJsInteropMethod(DartDOMData::current(), "_maybeWrap", 1, &wrapper); |
+ } |
} |
- if (object->IsArray()) { |
- RefPtr<JsArray> jsArray = JsArray::create(object.As<v8::Array>()); |
- return JsArray::toDart(jsArray); |
+ v8::Local<v8::Object> proxy; |
+ |
+ // Prevent creation of cross frame dart:html objects for classes other than Window. |
+ // Verify that the object is from the same context using the same check |
+ // we used to use in V8Converter. |
+ if (!object->CreationContext()->Global()->StrictEquals(DartUtilities::currentV8Context()->Global())) { |
+ // Short circuit creating dart:html wrappers for cross frame objects |
+ // other than window. |
+ // TODO(jacobr): handle cross frame Window objects differently to more |
+ // exactly match existing dart:html semantics. |
+ if (!object->CreationContext()->Global()->StrictEquals(object)) { |
+ Dart_SetField(wrapper, Dart_NewStringFromCString("_dartHtmlWrapper"), wrapper); |
+ } |
} |
+ ASSERT(Dart_IsInstance(wrapper)); |
+ // Simulate the behavior of the Dart dev compiler where new List() is |
+ // equivalent to a JavaScript array. We accomplish this by creating a |
+ // JavaScript object that fakes that it is a JavaScript array but is |
+ // actually backed by a Dart list. This is not a breaking change as |
+ // existing Dart-JS interop passed arrays as opaque Dart handles. |
+ // The jsify method can still be called if you wish to create a copy |
+ // of a json like Dart data structure. |
+ proxy = dartObjectTemplate()->InstanceTemplate()->NewInstance(); |
+ DartHandleProxy::writePointerToProxy(proxy, wrapper); |
+ object->SetHiddenValue(existingDartWrapperKey, proxy); |
+ return ret != 0 ? ret : wrapper; |
+} |
- RefPtr<JsObject> jsObject = JsObject::create(object); |
- return JsObject::toDart(jsObject); |
+void JsInterop::buildInteropPatchFiles(DartDOMData* domData, Vector<InteropPatchFile>* patches, Dart_Handle& exception) |
+{ |
+ // Build patch files implementing all external methods specified with new |
+ // style JS interop and JsObjectImpl, JsFunctionImpl, and JsArrayImpl |
+ // classes that implement all Dart types annoted with @Js. |
+ // The sole purpose of these classes is to ensure that checked mode |
+ // allows casting a JsObject to all types implemented by a JsObject. |
+ Dart_Handle externals = invokeTopLevelJsInteropMethod(domData, "_generateInteropPatchFiles", 0, 0); |
+ if (Dart_IsError(externals)) { |
+ exception = externals; |
+ return; |
+ } |
+ ASSERT(Dart_IsList(externals)); |
+ intptr_t externalsLength = 0; |
+ Dart_ListLength(externals, &externalsLength); |
+ ASSERT(externalsLength % 3 == 0); |
+ |
+ for (intptr_t i = 0; i < externalsLength; i += 3) { |
+ InteropPatchFile patch; |
+ |
+ Dart_Handle libraryUri = Dart_ListGetAt(externals, i); |
+ Dart_Handle patchFileUri = Dart_ListGetAt(externals, i + 1); |
+ Dart_Handle source = Dart_ListGetAt(externals, i + 2); |
+ ASSERT(Dart_IsString(libraryUri)); |
+ ASSERT(Dart_IsString(patchFileUri)); |
+ ASSERT(Dart_IsString(source)); |
+ patch.libraryUri = DartUtilities::toString(libraryUri); |
+ patch.patchFileUri = DartUtilities::toString(patchFileUri); |
+ patch.source = DartUtilities::toString(source); |
+ patches->append(patch); |
+ } |
} |
-static void maybeCreateJsObjectImplClass(DartDOMData* domData) |
+void JsInterop::initializeJsInterop(DartDOMData* domData, const Vector<InteropPatchFile>& patches, Dart_Handle& exception) |
{ |
DartJsInteropData* interopData = domData->jsInteropData(); |
// Skip if the JSObjectImpl class has already been defined. |
@@ -458,36 +578,54 @@ static void maybeCreateJsObjectImplClass(DartDOMData* domData) |
// all Dart types that have been passed to the dart:js registerJsInterfaces |
// method. The sole purpose of these classes is to ensure that checked mode |
// allows casting a JsObject to all types implemented by a JsObject. |
- Dart_Handle source = invokeTopLevelJsInteropMethod(domData, "_generateJsObjectImplPart", 0, 0); |
- ASSERT(Dart_IsString(source)); |
- Dart_Handle ret = Dart_LibraryLoadPatch(domData->jsLibrary(), Dart_NewStringFromCString("JsInteropImpl.dart"), source); |
- ALLOW_UNUSED_LOCAL(ret); |
- ASSERT(!Dart_IsError(ret)); |
+ Dart_Handle ret; |
+ for (size_t i = 0; i < patches.size(); ++i) { |
+ const InteropPatchFile& patch = patches[i]; |
+ Dart_Handle library = Dart_LookupLibrary(DartUtilities::safeStringToDartString(patch.libraryUri)); |
+ ASSERT(Dart_IsLibrary(library)); |
+ Dart_Handle patchFileUri = DartUtilities::safeStringToDartString(patch.patchFileUri); |
+ Dart_Handle source = DartUtilities::safeStringToDartString(patch.source); |
+ ret = Dart_LibraryLoadPatch(library, patchFileUri, source); |
+ if (Dart_IsError(ret)) { |
+ exception = ret; |
+ return; |
+ } |
+ } |
ret = Dart_FinalizeLoading(false); |
- ASSERT(!Dart_IsError(ret)); |
+ if (Dart_IsError(ret)) { |
+ exception = ret; |
+ return; |
+ } |
interopData->setJsObjectImplDefined(); |
- // Start of polyfill work to make Dart List proxies behave like JavaScript |
- // Arrays by monkey patching JavaScript Array and the List JavaScript |
- // proxies as needed. |
- v8::Context::Scope scope(DartUtilities::currentV8Context()); |
+ if (domData->isDOMEnabled()) { |
+ // Start of polyfill work to make Dart List proxies behave like JavaScript |
+ // Arrays by monkey patching JavaScript Array and the List JavaScript |
+ // proxies as needed. |
+ v8::Context::Scope scope(DartUtilities::currentV8Context()); |
- v8::Isolate* v8Isolate = v8::Isolate::GetCurrent(); |
+ v8::Isolate* v8Isolate = v8::Isolate::GetCurrent(); |
+ |
+ v8::Local<v8::Function> dartArrayConstructor = dartListTemplate()->GetFunction(); |
- v8::Local<v8::Function> dartArrayConstructor = dartListTemplate()->GetFunction(); |
+ DartUtilities::currentV8Context()->Global()->Set(v8::String::NewFromUtf8(v8Isolate, "$DartList"), |
+ dartArrayConstructor); |
+ V8ScriptRunner::compileAndRunInternalScript(v8::String::NewFromUtf8(v8Isolate, dartArrayPolyfill), v8Isolate); |
- DartUtilities::currentV8Context()->Global()->Set(v8::String::NewFromUtf8(v8Isolate, "$DartList"), |
- dartArrayConstructor); |
- V8ScriptRunner::compileAndRunInternalScript(v8::String::NewFromUtf8(v8Isolate, dartArrayPolyfill), v8Isolate); |
+ ret = Dart_Invoke(domData->jsLibrary(), Dart_NewStringFromCString("_registerAllJsInterfaces"), 0, 0); |
+ if (Dart_IsError(ret)) { |
+ exception = ret; |
+ return; |
+ } |
+ } |
} |
Dart_Handle JsObject::toDart(PassRefPtr<JsObject> jsObject) |
{ |
DartDOMData* domData = DartDOMData::current(); |
// We need to ensure JsObjectImpl exists before creating the wrapper. |
- maybeCreateJsObjectImplClass(domData); |
return DartDOMWrapper::createWrapper<JsObject>(domData, jsObject.get(), JsObject::dartClassId); |
} |
@@ -500,7 +638,6 @@ Dart_Handle JsFunction::toDart(PassRefPtr<JsFunction> jsFunction) |
{ |
DartDOMData* domData = DartDOMData::current(); |
// We need to ensure JsObjectImpl exists before creating the wrapper. |
- maybeCreateJsObjectImplClass(domData); |
return DartDOMWrapper::createWrapper<JsFunction>(domData, jsFunction.get(), JsFunction::dartClassId); |
} |
@@ -520,22 +657,16 @@ Dart_Handle JsArray::toDart(PassRefPtr<JsArray> jsArray) |
{ |
DartDOMData* domData = DartDOMData::current(); |
// We need to ensure JsArrayImpl exists before creating the wrapper. |
- maybeCreateJsObjectImplClass(domData); |
return DartDOMWrapper::createWrapper<JsArray>(domData, jsArray.get(), JsArray::dartClassId); |
} |
-JsArray::JsArray(v8::Local<v8::Array> v8Handle) : JsObject(v8Handle) { } |
+JsArray::JsArray(v8::Local<v8::Object> v8Handle) : JsObject(v8Handle) { } |
-PassRefPtr<JsArray> JsArray::create(v8::Local<v8::Array> v8Handle) |
+PassRefPtr<JsArray> JsArray::create(v8::Local<v8::Object> v8Handle) |
{ |
return adoptRef(new JsArray(v8Handle)); |
} |
-v8::Local<v8::Array> JsArray::localV8Array() |
-{ |
- return localV8Object().As<v8::Array>(); |
-} |
- |
namespace JsInteropInternal { |
typedef HashMap<Dart_Handle, v8::Handle<v8::Value> > DartHandleToV8Map; |
@@ -605,7 +736,7 @@ static void jsObjectConstructorCallback(Dart_NativeArguments args) |
// a JSObject. FIXME: evaluate if this is the right solution. |
// Alternately, we could throw an exception. |
if (ret->IsObject()) { |
- scopes.setReturnValue(JsObject::toDart(ret.As<v8::Object>())); |
+ scopes.setReturnValue(JsObject::toDart(ret.As<v8::Object>(), false)); |
} else { |
// This will throw an exception in Dart checked mode. |
scopes.setReturnValue(ret); |
@@ -872,7 +1003,7 @@ fail: |
static void newJsArrayCallback(Dart_NativeArguments args) |
{ |
JsInteropScopes scopes(args); |
- scopes.setReturnValue(JsObject::toDart(v8::Array::New(v8::Isolate::GetCurrent()))); |
+ scopes.setReturnValue(JsObject::toDart(v8::Array::New(v8::Isolate::GetCurrent()), false)); |
return; |
} |
@@ -916,10 +1047,10 @@ static void jsArrayLengthCallback(Dart_NativeArguments args) |
{ |
JsInteropScopes scopes(args); |
JsArray* receiver = DartDOMWrapper::receiver<JsArray>(args); |
- uint32_t length = receiver->localV8Array()->Length(); |
+ v8::Local<v8::Value> length = receiver->localV8Object()->Get(v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), "length")); |
if (scopes.handleJsException(&exception)) |
goto fail; |
- scopes.setReturnValueInteger(length); |
+ scopes.setReturnValue(length); |
return; |
} |
@@ -945,7 +1076,7 @@ static void fromBrowserObjectCallback(Dart_NativeArguments args) |
ASSERT(ret->IsObject()); |
if (scopes.handleJsException(&exception)) |
goto fail; |
- scopes.setReturnValue(JsObject::toDart(ret.As<v8::Object>())); |
+ scopes.setReturnValue(JsObject::toDart(ret.As<v8::Object>(), false)); |
return; |
} |
@@ -973,18 +1104,9 @@ static void applyCallback(Dart_NativeArguments args) |
// Use the global v8 object if no Dart thisArg was passed in. |
thisArg = DartUtilities::currentV8Context()->Global(); |
} else { |
- Dart_Handle jso = Dart_GetField(thisArgDart, Dart_NewStringFromCString("blink_jsObject")); |
- if (!Dart_IsError(jso) && DartDOMWrapper::subtypeOf(jso, JsObject::dartClassId)) { |
- // Use the blink JS Interop object. |
- JsObject* object = DartDOMWrapper::unwrapDartWrapper<JsObject>(domData, jso, exception); |
- if (exception) |
- thisArg = v8::Local<v8::Value>(); |
- thisArg = object->localV8Object(); |
- } else { |
- thisArg = JsInterop::fromDart(domData, thisArgDart, exception); |
- if (exception) |
- goto fail; |
- } |
+ thisArg = JsInterop::fromDart(domData, thisArgDart, exception); |
+ if (exception) |
+ goto fail; |
if (!thisArg->IsObject()) { |
exception = Dart_NewStringFromCString("thisArg is not an object"); |
goto fail; |
@@ -1082,13 +1204,12 @@ static void contextCallback(Dart_NativeArguments args) |
{ |
v8::Local<v8::Context> v8Context = DartUtilities::currentV8Context(); |
v8::Context::Scope scope(v8Context); |
- Dart_SetReturnValue(args, JsObject::toDart(v8Context->Global())); |
+ Dart_SetReturnValue(args, JsObject::toDart(v8Context->Global(), false)); |
} |
static void finalizeJsInterfacesCallback(Dart_NativeArguments args) |
{ |
- DartDOMData* domData = static_cast<DartDOMData*>(Dart_GetNativeIsolateData(args)); |
- maybeCreateJsObjectImplClass(domData); |
+ // Obsolete. |
} |
static void interfacesFinalizedCallback(Dart_NativeArguments args) |
@@ -1197,7 +1318,7 @@ static void jsifyCallback(Dart_NativeArguments args) |
// a JSObject. FIXME: evaluate if this is the right solution. |
// Alternately, we could throw an exception. |
if (ret->IsObject()) { |
- scopes.setReturnValue(JsObject::toDart(ret.As<v8::Object>())); |
+ scopes.setReturnValue(JsObject::toDart(ret.As<v8::Object>(), false)); |
} else { |
// This will throw an exception in Dart checked mode. |
scopes.setReturnValue(ret); |
@@ -1233,6 +1354,31 @@ fail: |
ASSERT_NOT_REACHED(); |
} |
+ |
+static void withThisCallbackNoWrap(Dart_NativeArguments args) |
+{ |
+ Dart_Handle exception = 0; |
+ { |
+ JsInteropScopes scopes(args); |
+ Dart_Handle function = Dart_GetNativeArgument(args, 0); |
+ DartDOMData* domData = static_cast<DartDOMData*>(Dart_GetNativeIsolateData(args)); |
+ ASSERT(DartUtilities::isFunction(domData, function)); |
+ |
+ v8::Local<v8::Object> proxy = dartFunctionTemplateNoWrap()->InstanceTemplate()->NewInstance(); |
+ DartHandleProxy::writePointerToProxy(proxy, function); |
+ |
+ v8::Local<v8::Function> ret = v8::Local<v8::Function>::Cast(domData->jsInteropData()->captureThisFunction()->Call(proxy, 0, 0)); |
+ |
+ if (scopes.handleJsException(&exception)) |
+ goto fail; |
+ scopes.setReturnValue(ret); |
+ return; |
+ } |
+fail: |
+ Dart_ThrowException(exception); |
+ ASSERT_NOT_REACHED(); |
+} |
+ |
} |
static DartNativeEntry nativeEntries[] = { |
@@ -1242,6 +1388,7 @@ static DartNativeEntry nativeEntries[] = { |
{ JsInteropInternal::interfacesFinalizedCallback, 0, "Js_interfacesFinalized_Callback" }, |
{ JsInteropInternal::jsifyCallback, 1, "JsObject_jsify" }, |
{ JsInteropInternal::withThisCallback, 1, "JsFunction_withThis" }, |
+ { JsInteropInternal::withThisCallbackNoWrap, 1, "JsFunction_withThisNoWrap" }, |
{ JsInterop::jsInteropGetterCallback, 2, "JsObject_[]" }, |
{ JsInteropInternal::setterCallback, 3, "JsObject_[]=" }, |
{ JsInteropInternal::hashCodeCallback, 1, "JsObject_hashCode" }, |
@@ -1424,7 +1571,7 @@ void arrayHelper1Arg(const v8::FunctionCallbackInfo<v8::Value>& info, const char |
if (info.Length() == 0) { |
e = Dart_Null(); |
} else { |
- e = JsInterop::toDart(info[0]); |
+ e = JsInterop::toDart(info[0], false); |
} |
Dart_Handle args[2] = { handle, e }; |
Dart_Handle ret = Dart_Invoke(domData->jsLibrary(), Dart_NewStringFromCString(methodName), 2, args); |
@@ -1442,7 +1589,7 @@ void arrayHelperWithArgsAsList(const v8::FunctionCallbackInfo<v8::Value>& info, |
int length = info.Length(); |
Dart_Handle argsList = Dart_NewList(length); |
for (int i = 0; i < length; ++i) { |
- Dart_ListSetAt(argsList, i, JsInterop::toDart(info[i])); |
+ Dart_ListSetAt(argsList, i, JsInterop::toDart(info[i], false)); |
} |
// Note: this is also just info.Holder(). |
Dart_Handle args[2] = { handle, argsList }; |
@@ -1485,7 +1632,7 @@ static void arrayNamedPropertySetter(v8::Local<v8::String> property, v8::Local<v |
DartScopes scopes(info.Holder()); |
Dart_Handle handle = scopes.handle; |
DartDOMData* domData = DartDOMData::current(); |
- Dart_Handle args[2] = { handle, JsInterop::toDart(value) }; |
+ Dart_Handle args[2] = { handle, JsInterop::toDart(value, true) }; |
Dart_Handle ret = Dart_Invoke(domData->jsLibrary(), Dart_NewStringFromCString("_setListLength"), 2, args); |
setJsReturnValue(domData, info, ret); |
} |
@@ -1618,6 +1765,36 @@ v8::Local<v8::FunctionTemplate> dartListTemplate() |
return proxyTemplateLocal; |
} |
+void dartObjectToStringCallback(const v8::FunctionCallbackInfo<v8::Value>& info) |
+{ |
+ if (handleNonDartProxyThis(info, "toString")) { |
+ return; |
+ } |
+ DartScopes scopes(info.Holder()); |
+ DartDOMData* domData = DartDOMData::current(); |
+ Dart_Handle handle = scopes.handle; |
+ setJsReturnValue(domData, info, Dart_ToString(handle)); |
+} |
+ |
+static v8::Local<v8::FunctionTemplate> dartObjectTemplate() |
+{ |
+ DEFINE_STATIC_LOCAL(v8::Persistent<v8::FunctionTemplate>, proxyTemplate, ()); |
+ v8::Local<v8::FunctionTemplate> proxyTemplateLocal; |
+ v8::Isolate* v8Isolate = v8::Isolate::GetCurrent(); |
+ if (proxyTemplate.IsEmpty()) { |
+ proxyTemplate.Reset(v8Isolate, v8::FunctionTemplate::New(v8Isolate)); |
+ proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, proxyTemplate); |
+ v8::Local<v8::ObjectTemplate> protoTemplate = proxyTemplateLocal->PrototypeTemplate(); |
+ protoTemplate->Set(v8::String::NewFromUtf8(v8Isolate, "toString"), v8::FunctionTemplate::New(v8Isolate, dartObjectToStringCallback)); |
+ |
+ proxyTemplateLocal->SetClassName(v8::String::NewFromUtf8(v8Isolate, "DartObject")); |
+ setupInstanceTemplate(proxyTemplateLocal); |
+ } else { |
+ proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, proxyTemplate); |
+ } |
+ return proxyTemplateLocal; |
+} |
+ |
void JsInterop::jsInteropGetterCallback(Dart_NativeArguments args) |
{ |
JsInteropInternal::getterCallback(args); |