| Index: sky/engine/bindings-dart/core/dart/DartJsInterop.cpp
|
| diff --git a/sky/engine/bindings-dart/core/dart/DartJsInterop.cpp b/sky/engine/bindings-dart/core/dart/DartJsInterop.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..4b4e8f9900d55c8fc3cbf0ad5d1e42a4883949f1
|
| --- /dev/null
|
| +++ b/sky/engine/bindings-dart/core/dart/DartJsInterop.cpp
|
| @@ -0,0 +1,1053 @@
|
| +/*
|
| + * Copyright (C) 2013 Google Inc. All rights reserved.
|
| + *
|
| + * Redistribution and use in source and binary forms, with or without
|
| + * modification, are permitted provided that the following conditions are
|
| + * met:
|
| + *
|
| + * * Redistributions of source code must retain the above copyright
|
| + * notice, this list of conditions and the following disclaimer.
|
| + * * Redistributions in binary form must reproduce the above
|
| + * copyright notice, this list of conditions and the following disclaimer
|
| + * in the documentation and/or other materials provided with the
|
| + * distribution.
|
| + * * Neither the name of Google Inc. nor the names of its
|
| + * contributors may be used to endorse or promote products derived from
|
| + * this software without specific prior written permission.
|
| + *
|
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| + */
|
| +#include "config.h"
|
| +
|
| +#include "bindings/core/dart/DartJsInterop.h"
|
| +
|
| +#include "bindings/core/dart/DartDOMWrapper.h"
|
| +#include "bindings/core/dart/DartHandleProxy.h"
|
| +#include "bindings/core/dart/DartJsInteropData.h"
|
| +#include "bindings/core/dart/DartPersistentValue.h"
|
| +#include "bindings/core/dart/DartUtilities.h"
|
| +#include "bindings/core/dart/V8Converter.h"
|
| +#include "bindings/core/v8/V8Binding.h"
|
| +#include "bindings/core/v8/V8RecursionScope.h"
|
| +#include "bindings/core/v8/V8ScriptRunner.h"
|
| +
|
| +#include "wtf/StdLibExtras.h"
|
| +
|
| +#include <dart_api.h>
|
| +#include <limits>
|
| +
|
| +namespace blink {
|
| +
|
| +const int JsObject::dartClassId = _JsObjectClassId;
|
| +const int JsFunction::dartClassId = _JsFunctionClassId;
|
| +const int JsArray::dartClassId = _JsArrayClassId;
|
| +
|
| +static v8::Local<v8::FunctionTemplate> dartFunctionTemplate();
|
| +static v8::Local<v8::FunctionTemplate> dartObjectTemplate();
|
| +
|
| +template<typename CallbackInfo>
|
| +void setJsReturnValue(DartDOMData* domData, CallbackInfo info, Dart_Handle result)
|
| +{
|
| + if (Dart_IsError(result)) {
|
| + v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
|
| + V8ThrowException::throwException(v8::String::NewFromUtf8(v8Isolate, Dart_GetError(result)), v8Isolate);
|
| + } else {
|
| + Dart_Handle exception = 0;
|
| + v8::Local<v8::Value> ret = JsInterop::fromDart(domData, result, exception);
|
| + if (exception) {
|
| + V8ThrowException::throwException(V8Converter::stringToV8(Dart_ToString(exception)), v8::Isolate::GetCurrent());
|
| + return;
|
| + }
|
| + v8SetReturnValue(info, ret);
|
| + }
|
| +}
|
| +
|
| +static void functionInvocationCallback(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]));
|
| + }
|
| +
|
| + 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)));
|
| + }
|
| +
|
| + 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();
|
| + instanceTemplate->SetInternalFieldCount(1);
|
| + return instanceTemplate;
|
| +}
|
| +
|
| +static v8::Local<v8::FunctionTemplate> dartFunctionTemplate()
|
| +{
|
| + DEFINE_STATIC_LOCAL(v8::Persistent<v8::FunctionTemplate>, proxyTemplate, ());
|
| + v8::Local<v8::FunctionTemplate> proxyTemplateLocal;
|
| + v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
|
| + if (proxyTemplate.IsEmpty()) {
|
| + proxyTemplate.Reset(v8::Isolate::GetCurrent(), v8::FunctionTemplate::New(v8Isolate));
|
| + proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, proxyTemplate);
|
| + v8::Local<v8::ObjectTemplate> instanceTemplate = setupInstanceTemplate(proxyTemplateLocal);
|
| +
|
| + instanceTemplate->SetCallAsFunctionHandler(&functionInvocationCallback);
|
| + } else {
|
| + proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, proxyTemplate);
|
| + }
|
| + return proxyTemplateLocal;
|
| +}
|
| +
|
| +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);
|
| + proxyTemplateLocal->SetClassName(v8::String::NewFromUtf8(v8Isolate, "DartObject"));
|
| + setupInstanceTemplate(proxyTemplateLocal);
|
| + } else {
|
| + proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, proxyTemplate);
|
| + }
|
| + return proxyTemplateLocal;
|
| +}
|
| +
|
| +/**
|
| + * Helper class to manage scopes needed for JSInterop code.
|
| + */
|
| +class JsInteropScopes {
|
| +public:
|
| + Dart_NativeArguments args;
|
| + v8::Context::Scope v8Scope;
|
| + v8::TryCatch tryCatch;
|
| +
|
| + JsInteropScopes(Dart_NativeArguments args)
|
| + : args(args)
|
| + , v8Scope(DartUtilities::currentV8Context())
|
| + {
|
| + ASSERT(v8::Isolate::GetCurrent());
|
| + }
|
| +
|
| + ~JsInteropScopes()
|
| + {
|
| + // The user is expected to call handleJsException before the scope is
|
| + // closed so that V8 exceptions are properly sent back to Dart.
|
| + ASSERT(!tryCatch.HasCaught());
|
| + }
|
| +
|
| + bool handleJsException(Dart_Handle* exception)
|
| + {
|
| + if (!tryCatch.HasCaught())
|
| + return false;
|
| + // FIXME: terminate v8 if tryCatch.CanContinue() is false.
|
| + ASSERT(tryCatch.CanContinue());
|
| + ASSERT(exception);
|
| + v8::Handle<v8::Value> ex(tryCatch.Exception()->ToString());
|
| + if (ex.IsEmpty()) {
|
| + *exception = Dart_NewStringFromCString("Empty JavaScript exception");
|
| + } else {
|
| + *exception = V8Converter::stringToDart(ex);
|
| + }
|
| + tryCatch.Reset();
|
| + return true;
|
| + }
|
| +
|
| + void setReturnValue(Dart_Handle ret)
|
| + {
|
| + ASSERT(!tryCatch.HasCaught());
|
| + Dart_SetReturnValue(args, ret);
|
| + }
|
| +
|
| + void setReturnValue(v8::Local<v8::Value> ret)
|
| + {
|
| + ASSERT(!tryCatch.HasCaught());
|
| + Dart_SetReturnValue(args, JsInterop::toDart(ret));
|
| + ASSERT(!tryCatch.HasCaught());
|
| + }
|
| +
|
| + void setReturnValueInteger(int64_t ret)
|
| + {
|
| + ASSERT(!tryCatch.HasCaught());
|
| + Dart_SetIntegerReturnValue(args, ret);
|
| + }
|
| +};
|
| +
|
| +PassRefPtr<JsObject> JsObject::create(v8::Local<v8::Object> v8Handle)
|
| +{
|
| + return adoptRef(new JsObject(v8Handle));
|
| +}
|
| +
|
| +v8::Local<v8::Value> JsInterop::fromDart(DartDOMData* domData, Dart_Handle handle, Dart_Handle& exception)
|
| +{
|
| + v8::Handle<v8::Value> value = V8Converter::toV8IfPrimitive(domData, handle, exception);
|
| + if (!value.IsEmpty() || exception)
|
| + return value;
|
| +
|
| + value = V8Converter::toV8IfBrowserNative(domData, handle, exception);
|
| + if (!value.IsEmpty() || exception)
|
| + return value;
|
| +
|
| + if (DartDOMWrapper::subtypeOf(handle, JsObject::dartClassId)) {
|
| + JsObject* object = DartDOMWrapper::unwrapDartWrapper<JsObject>(domData, handle, exception);
|
| + if (exception)
|
| + return v8::Local<v8::Value>();
|
| + return object->localV8Object();
|
| + }
|
| +
|
| + if (DartUtilities::isFunction(domData, handle)) {
|
| + v8::Local<v8::Object> functionProxy = dartFunctionTemplate()->InstanceTemplate()->NewInstance();
|
| + DartHandleProxy::writePointerToProxy(functionProxy, handle);
|
| + // The raw functionProxy doesn't behave enough like a true JS function
|
| + // so we wrap it in a true JS function.
|
| + return domData->jsInteropData()->wrapDartFunction()->Call(functionProxy, 0, 0);
|
| + }
|
| +
|
| + v8::Local<v8::Object> proxy;
|
| + ASSERT(Dart_IsInstance(handle));
|
| + proxy = dartObjectTemplate()->InstanceTemplate()->NewInstance();
|
| + DartHandleProxy::writePointerToProxy(proxy, handle);
|
| + v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
|
| + proxy->SetHiddenValue(v8::String::NewFromUtf8(v8Isolate, "dartProxy"), v8::Boolean::New(v8Isolate, true));
|
| +
|
| + return proxy;
|
| +}
|
| +
|
| +JsObject::JsObject(v8::Local<v8::Object> v8Handle)
|
| +{
|
| + v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
| + v8::Persistent<v8::Object> persistentHandle;
|
| + v8Object.Reset(isolate, v8Handle);
|
| +}
|
| +
|
| +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 handle = V8Converter::toDartIfPrimitive(v8Handle);
|
| + if (handle)
|
| + return handle;
|
| +
|
| + ASSERT(v8Handle->IsObject());
|
| + v8::Handle<v8::Object> object = v8Handle.As<v8::Object>();
|
| + Dart_Handle exception = 0;
|
| + handle = V8Converter::toDartIfBrowserNative(object, object->CreationContext()->GetIsolate(), exception);
|
| + ASSERT(!exception);
|
| + if (handle)
|
| + return handle;
|
| +
|
| + // Unwrap objects passed from Dart to JS that are being passed back to
|
| + // Dart. FIXME: we do not yet handle unwrapping JS functions passed
|
| + // from Dart to JS as we have to wrap them with true JS Function objects.
|
| + // If this use case is important we can support it at the cost of hanging
|
| + // an extra expando off the JS function wrapping the Dart function.
|
| + if (DartHandleProxy::isDartProxy(v8Handle)) {
|
| + DartPersistentValue* scriptValue = DartHandleProxy::readPointerFromProxy(v8Handle);
|
| + ASSERT(scriptValue->isIsolateAlive());
|
| + return scriptValue->value();
|
| + }
|
| +
|
| + return JsObject::toDart(object);
|
| +}
|
| +
|
| +Dart_Handle JsObject::toDart(v8::Local<v8::Object> object)
|
| +{
|
| + // FIXME: perform caching so that === can be used.
|
| + if (object->IsFunction()) {
|
| + RefPtr<JsFunction> jsFunction = JsFunction::create(object.As<v8::Function>());
|
| + return JsFunction::toDart(jsFunction);
|
| + }
|
| +
|
| + if (object->IsArray()) {
|
| + RefPtr<JsArray> jsArray = JsArray::create(object.As<v8::Array>());
|
| + return JsArray::toDart(jsArray);
|
| + }
|
| +
|
| + RefPtr<JsObject> jsObject = JsObject::create(object);
|
| + return JsObject::toDart(jsObject);
|
| +}
|
| +
|
| +Dart_Handle JsObject::toDart(PassRefPtr<JsObject> jsObject)
|
| +{
|
| + return DartDOMWrapper::createWrapper<JsObject>(DartDOMData::current(), jsObject.get(), JsObject::dartClassId);
|
| +}
|
| +
|
| +JsObject::~JsObject()
|
| +{
|
| + v8Object.Reset();
|
| +}
|
| +
|
| +Dart_Handle JsFunction::toDart(PassRefPtr<JsFunction> jsFunction)
|
| +{
|
| + return DartDOMWrapper::createWrapper<JsFunction>(DartDOMData::current(), jsFunction.get(), JsFunction::dartClassId);
|
| +}
|
| +
|
| +JsFunction::JsFunction(v8::Local<v8::Function> v8Handle) : JsObject(v8Handle) { }
|
| +
|
| +PassRefPtr<JsFunction> JsFunction::create(v8::Local<v8::Function> v8Handle)
|
| +{
|
| + return adoptRef(new JsFunction(v8Handle));
|
| +}
|
| +
|
| +v8::Local<v8::Function> JsFunction::localV8Function()
|
| +{
|
| + return localV8Object().As<v8::Function>();
|
| +}
|
| +
|
| +Dart_Handle JsArray::toDart(PassRefPtr<JsArray> jsArray)
|
| +{
|
| + return DartDOMWrapper::createWrapper<JsArray>(DartDOMData::current(), jsArray.get(), JsArray::dartClassId);
|
| +}
|
| +
|
| +JsArray::JsArray(v8::Local<v8::Array> v8Handle) : JsObject(v8Handle) { }
|
| +
|
| +PassRefPtr<JsArray> JsArray::create(v8::Local<v8::Array> 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;
|
| +v8::Handle<v8::Value> jsifyHelper(DartDOMData*, Dart_Handle value, DartHandleToV8Map&, Dart_Handle& exception);
|
| +
|
| +void argsListToV8(DartDOMData* domData, Dart_Handle args, Vector<v8::Local<v8::Value> >* v8Args, Dart_Handle& exception)
|
| +{
|
| + if (Dart_IsNull(args))
|
| + return;
|
| +
|
| + if (!Dart_IsList(args)) {
|
| + exception = Dart_NewStringFromCString("args not type list");
|
| + return;
|
| + }
|
| +
|
| + intptr_t argsLength = 0;
|
| + Dart_ListLength(args, &argsLength);
|
| + for (intptr_t i = 0; i < argsLength; i++) {
|
| + v8Args->append(JsInterop::fromDart(domData, Dart_ListGetAt(args, i), exception));
|
| + if (exception)
|
| + return;
|
| + }
|
| +}
|
| +
|
| +void argsListToV8DebuggerOnly(DartDOMData* domData, Dart_Handle args, Vector<v8::Local<v8::Value> >* v8Args, Dart_Handle& exception)
|
| +{
|
| + if (Dart_IsNull(args))
|
| + return;
|
| +
|
| + if (!Dart_IsList(args)) {
|
| + exception = Dart_NewStringFromCString("args not type list");
|
| + return;
|
| + }
|
| +
|
| + intptr_t argsLength = 0;
|
| + Dart_ListLength(args, &argsLength);
|
| + for (intptr_t i = 0; i < argsLength; i++) {
|
| + v8Args->append(DartHandleProxy::create(Dart_ListGetAt(args, i)));
|
| + }
|
| +}
|
| +
|
| +static void jsObjectConstructorCallback(Dart_NativeArguments args)
|
| +{
|
| + Dart_Handle exception = 0;
|
| + {
|
| + JsInteropScopes scopes(args);
|
| + DartDOMData* domData = static_cast<DartDOMData*>(Dart_GetNativeIsolateData(args));
|
| + v8::Local<v8::Value> constructorArg = JsInterop::fromDart(domData, Dart_GetNativeArgument(args, 0), exception);
|
| + if (exception)
|
| + goto fail;
|
| +
|
| + if (!constructorArg->IsFunction()) {
|
| + exception = Dart_NewStringFromCString("constructor not a function");
|
| + goto fail;
|
| + }
|
| +
|
| + Vector<v8::Local<v8::Value> > v8Args;
|
| + argsListToV8(domData, Dart_GetNativeArgument(args, 1), &v8Args, exception);
|
| +
|
| + v8::Local<v8::Value> ret = constructorArg.As<v8::Function>()->CallAsConstructor(v8Args.size(), v8Args.data());
|
| + crashIfV8IsDead();
|
| +
|
| + if (scopes.handleJsException(&exception))
|
| + goto fail;
|
| +
|
| + // Intentionally skip auto-conversion in this case as the user expects
|
| + // 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>()));
|
| + } else {
|
| + // This will throw an exception in Dart checked mode.
|
| + scopes.setReturnValue(ret);
|
| + }
|
| + return;
|
| + }
|
| +
|
| +fail:
|
| + Dart_ThrowException(exception);
|
| + ASSERT_NOT_REACHED();
|
| +}
|
| +
|
| +static void identityEqualityCallback(Dart_NativeArguments args)
|
| +{
|
| + Dart_Handle exception = 0;
|
| + {
|
| + JsInteropScopes scopes(args);
|
| + DartDOMData* domData = static_cast<DartDOMData*>(Dart_GetNativeIsolateData(args));
|
| + v8::Local<v8::Value> a = JsInterop::fromDart(domData, Dart_GetNativeArgument(args, 0), exception);
|
| + if (exception)
|
| + goto fail;
|
| + v8::Local<v8::Value> b = JsInterop::fromDart(domData, Dart_GetNativeArgument(args, 1), exception);
|
| + if (exception)
|
| + goto fail;
|
| +
|
| + bool strictEquals = a->StrictEquals(b);
|
| +
|
| + if (scopes.handleJsException(&exception))
|
| + goto fail;
|
| + scopes.setReturnValue(DartUtilities::boolToDart(strictEquals));
|
| + return;
|
| + }
|
| +
|
| +fail:
|
| + Dart_ThrowException(exception);
|
| + ASSERT_NOT_REACHED();
|
| +}
|
| +
|
| +static void getterCallback(Dart_NativeArguments args)
|
| +{
|
| + Dart_Handle exception = 0;
|
| + {
|
| + JsInteropScopes scopes(args);
|
| + JsObject* receiver = DartDOMWrapper::receiver<JsObject>(args);
|
| + v8::Local<v8::Object> v8Receiver = receiver->localV8Object();
|
| + Dart_Handle index = Dart_GetNativeArgument(args, 1);
|
| + uint64_t intIndex = 0;
|
| + v8::Local<v8::Value> ret;
|
| +
|
| + if (Dart_IsInteger(index)) {
|
| + bool isUint64 = false;
|
| + Dart_IntegerFitsIntoUint64(index, &isUint64);
|
| + if (isUint64) {
|
| + Dart_Handle ALLOW_UNUSED result = Dart_IntegerToUint64(index, &intIndex);
|
| + if (intIndex <= std::numeric_limits<uint32_t>::max()) {
|
| + ASSERT(!Dart_IsError(result));
|
| + ret = v8Receiver->Get((uint32_t)intIndex);
|
| + } else {
|
| + ret = v8Receiver->Get(V8Converter::numberToV8(index));
|
| + }
|
| + } else {
|
| + ret = v8Receiver->Get(V8Converter::numberToV8(index));
|
| + }
|
| + } else if (Dart_IsString(index)) {
|
| + ret = v8Receiver->Get(V8Converter::stringToV8(index));
|
| + } else if (Dart_IsNumber(index)) {
|
| + ret = v8Receiver->Get(V8Converter::numberToV8(index));
|
| + } else {
|
| + ret = v8Receiver->Get(V8Converter::stringToV8(Dart_ToString(index)));
|
| + }
|
| +
|
| + if (scopes.handleJsException(&exception))
|
| + goto fail;
|
| + scopes.setReturnValue(ret);
|
| + return;
|
| + }
|
| +
|
| +fail:
|
| + Dart_ThrowException(exception);
|
| + ASSERT_NOT_REACHED();
|
| +}
|
| +
|
| +static void hasPropertyCallback(Dart_NativeArguments args)
|
| +{
|
| + Dart_Handle exception = 0;
|
| + {
|
| + JsInteropScopes scopes(args);
|
| + JsObject* receiver = DartDOMWrapper::receiver<JsObject>(args);
|
| + v8::Local<v8::Object> v8Receiver = receiver->localV8Object();
|
| + Dart_Handle property = Dart_GetNativeArgument(args, 1);
|
| +
|
| + if (!Dart_IsString(property))
|
| + property = Dart_ToString(property);
|
| +
|
| + bool hasProperty = v8Receiver->Has(V8Converter::stringToV8(property));
|
| + if (scopes.handleJsException(&exception))
|
| + goto fail;
|
| + scopes.setReturnValue(DartUtilities::boolToDart(hasProperty));
|
| + return;
|
| + }
|
| +
|
| +fail:
|
| + Dart_ThrowException(exception);
|
| + ASSERT_NOT_REACHED();
|
| +}
|
| +
|
| +static void deletePropertyCallback(Dart_NativeArguments args)
|
| +{
|
| + Dart_Handle exception = 0;
|
| + {
|
| + JsInteropScopes scopes(args);
|
| + JsObject* receiver = DartDOMWrapper::receiver<JsObject>(args);
|
| + v8::Local<v8::Object> v8Receiver = receiver->localV8Object();
|
| + Dart_Handle property = Dart_GetNativeArgument(args, 1);
|
| + if (!Dart_IsString(property))
|
| + property = Dart_ToString(property);
|
| +
|
| + v8Receiver->Delete(V8Converter::stringToV8(property));
|
| + if (scopes.handleJsException(&exception))
|
| + goto fail;
|
| + return;
|
| + }
|
| +
|
| +fail:
|
| + Dart_ThrowException(exception);
|
| + ASSERT_NOT_REACHED();
|
| +}
|
| +
|
| +static void instanceofCallback(Dart_NativeArguments args)
|
| +{
|
| + Dart_Handle exception = 0;
|
| + {
|
| + JsInteropScopes scopes(args);
|
| + DartDOMData* domData = static_cast<DartDOMData*>(Dart_GetNativeIsolateData(args));
|
| + JsObject* receiver = DartDOMWrapper::receiver<JsObject>(args);
|
| + v8::Local<v8::Object> v8Receiver = receiver->localV8Object();
|
| + v8::Local<v8::Value> type = JsInterop::fromDart(domData, Dart_GetNativeArgument(args, 1), exception);
|
| +
|
| + // FIXME: we could optimize the following lines slightly as the return
|
| + // type is bool.
|
| + v8::Local<v8::Value> ret = domData->jsInteropData()->instanceofFunction()->Call(v8Receiver, 1, &type);
|
| + if (scopes.handleJsException(&exception))
|
| + goto fail;
|
| + scopes.setReturnValue(ret);
|
| + return;
|
| + }
|
| +
|
| +fail:
|
| + Dart_ThrowException(exception);
|
| + ASSERT_NOT_REACHED();
|
| +}
|
| +
|
| +static void setterCallback(Dart_NativeArguments args)
|
| +{
|
| + Dart_Handle exception = 0;
|
| + {
|
| + JsInteropScopes scopes(args);
|
| + DartDOMData* domData = static_cast<DartDOMData*>(Dart_GetNativeIsolateData(args));
|
| + JsObject* receiver = DartDOMWrapper::receiver<JsObject>(args);
|
| + v8::Local<v8::Object> v8Receiver = receiver->localV8Object();
|
| + Dart_Handle index = Dart_GetNativeArgument(args, 1);
|
| + v8::Local<v8::Value> value = JsInterop::fromDart(domData, Dart_GetNativeArgument(args, 2), exception);
|
| + if (exception)
|
| + goto fail;
|
| + uint64_t intIndex = 0;
|
| + bool ret = false;
|
| + if (Dart_IsInteger(index)) {
|
| + bool isUint64 = false;
|
| + Dart_IntegerFitsIntoUint64(index, &isUint64);
|
| + if (isUint64) {
|
| + Dart_Handle ALLOW_UNUSED result = Dart_IntegerToUint64(index, &intIndex);
|
| + if (intIndex <= std::numeric_limits<uint32_t>::max()) {
|
| + ASSERT(!Dart_IsError(result));
|
| + ret = v8Receiver->Set((uint32_t)intIndex, value);
|
| + } else {
|
| + ret = v8Receiver->Set(V8Converter::numberToV8(index), value);
|
| + }
|
| + } else {
|
| + ret = v8Receiver->Set(V8Converter::numberToV8(index), value);
|
| + }
|
| + } else if (Dart_IsString(index)) {
|
| + ret = v8Receiver->Set(V8Converter::stringToV8(index), value);
|
| + } else if (Dart_IsNumber(index)) {
|
| + ret = v8Receiver->Set(V8Converter::numberToV8(index), value);
|
| + } else {
|
| + ret = v8Receiver->Set(V8Converter::stringToV8(Dart_ToString(index)), value);
|
| + }
|
| +
|
| + if (scopes.handleJsException(&exception))
|
| + goto fail;
|
| + scopes.setReturnValue(DartUtilities::boolToDart(ret));
|
| + return;
|
| + }
|
| +
|
| +fail:
|
| + Dart_ThrowException(exception);
|
| + ASSERT_NOT_REACHED();
|
| +}
|
| +
|
| +static void hashCodeCallback(Dart_NativeArguments args)
|
| +{
|
| + Dart_Handle exception = 0;
|
| + {
|
| + JsInteropScopes scopes(args);
|
| + JsObject* receiver = DartDOMWrapper::receiver<JsObject>(args);
|
| + int hashCode = receiver->localV8Object()->GetIdentityHash();
|
| + // FIXME: salt the v8 hashcode so we don't leak information about v8
|
| + // memory allocation.
|
| + if (scopes.handleJsException(&exception))
|
| + goto fail;
|
| + scopes.setReturnValueInteger(hashCode);
|
| + return;
|
| + }
|
| +
|
| +fail:
|
| + Dart_ThrowException(exception);
|
| + ASSERT_NOT_REACHED();
|
| +}
|
| +
|
| +static void callMethodCallback(Dart_NativeArguments args)
|
| +{
|
| + Dart_Handle exception = 0;
|
| + {
|
| + JsInteropScopes scopes(args);
|
| + DartDOMData* domData = static_cast<DartDOMData*>(Dart_GetNativeIsolateData(args));
|
| + JsObject* receiver = DartDOMWrapper::receiver<JsObject>(args);
|
| + v8::Local<v8::Object> v8Receiver = receiver->localV8Object();
|
| +
|
| + Dart_Handle name = Dart_GetNativeArgument(args, 1);
|
| + Vector<v8::Local<v8::Value> > v8Args;
|
| + argsListToV8(domData, Dart_GetNativeArgument(args, 2), &v8Args, exception);
|
| + if (exception)
|
| + goto fail;
|
| + if (!Dart_IsString(name))
|
| + name = Dart_ToString(name);
|
| +
|
| + v8::Local<v8::Value> value = v8Receiver->Get(V8Converter::stringToV8(name));
|
| + v8::Local<v8::Value> ret;
|
| + if (value->IsFunction()) {
|
| + ret = V8ScriptRunner::callFunction(value.As<v8::Function>(), DartUtilities::scriptExecutionContext(), receiver->localV8Object(), v8Args.size(), v8Args.data(), v8::Isolate::GetCurrent());
|
| + } else if (value->IsObject()) {
|
| + ret = V8ScriptRunner::callAsFunction(v8::Isolate::GetCurrent(), value.As<v8::Object>(), receiver->localV8Object(), v8Args.size(), v8Args.data());
|
| + } else {
|
| + // FIXME: we currently convert this exception to a NoSuchMethod
|
| + // exception in the Dart code that wraps this native method.
|
| + // Consider throwing a NoSuchMethod exception directly instead.
|
| + exception = Dart_NewStringFromCString("property is not a function");
|
| + goto fail;
|
| + }
|
| +
|
| + if (scopes.handleJsException(&exception))
|
| + goto fail;
|
| + scopes.setReturnValue(ret);
|
| + return;
|
| + }
|
| +
|
| +fail:
|
| + Dart_ThrowException(exception);
|
| + ASSERT_NOT_REACHED();
|
| +}
|
| +
|
| +static void newJsArrayCallback(Dart_NativeArguments args)
|
| +{
|
| + JsInteropScopes scopes(args);
|
| + scopes.setReturnValue(JsObject::toDart(v8::Array::New(v8::Isolate::GetCurrent())));
|
| + return;
|
| +}
|
| +
|
| +static void newJsArrayFromSafeListCallback(Dart_NativeArguments args)
|
| +{
|
| + Dart_Handle exception = 0;
|
| + {
|
| + JsInteropScopes scopes(args);
|
| + DartDOMData* domData = static_cast<DartDOMData*>(Dart_GetNativeIsolateData(args));
|
| + Dart_Handle list = Dart_GetNativeArgument(args, 0);
|
| + // Code on the Dart side insures this arg is a native Dart list.
|
| + ASSERT(Dart_IsList(list));
|
| +
|
| + intptr_t length = 0;
|
| + Dart_Handle result = Dart_ListLength(list, &length);
|
| + ASSERT(!Dart_IsError(result));
|
| + v8::Local<v8::Array> array = v8::Array::New(v8::Isolate::GetCurrent(), length);
|
| +
|
| + for (intptr_t i = 0; i < length; ++i) {
|
| + result = Dart_ListGetAt(list, i);
|
| + ASSERT(!Dart_IsError(result));
|
| + v8::Handle<v8::Value> v8value = JsInterop::fromDart(domData, result, exception);
|
| + if (exception)
|
| + goto fail;
|
| +
|
| + array->Set(i, v8value);
|
| + }
|
| + scopes.setReturnValue(array);
|
| + return;
|
| + }
|
| +
|
| +fail:
|
| + Dart_ThrowException(exception);
|
| + ASSERT_NOT_REACHED();
|
| +}
|
| +
|
| +
|
| +static void jsArrayLengthCallback(Dart_NativeArguments args)
|
| +{
|
| + Dart_Handle exception = 0;
|
| + {
|
| + JsInteropScopes scopes(args);
|
| + JsArray* receiver = DartDOMWrapper::receiver<JsArray>(args);
|
| + uint32_t length = receiver->localV8Array()->Length();
|
| + if (scopes.handleJsException(&exception))
|
| + goto fail;
|
| + scopes.setReturnValueInteger(length);
|
| + return;
|
| + }
|
| +
|
| +fail:
|
| + Dart_ThrowException(exception);
|
| + ASSERT_NOT_REACHED();
|
| +}
|
| +
|
| +static void fromBrowserObjectCallback(Dart_NativeArguments args)
|
| +{
|
| + Dart_Handle exception = 0;
|
| + {
|
| + JsInteropScopes scopes(args);
|
| + DartDOMData* domData = static_cast<DartDOMData*>(Dart_GetNativeIsolateData(args));
|
| +
|
| + v8::Local<v8::Value> ret = V8Converter::toV8IfBrowserNative(domData, Dart_GetNativeArgument(args, 0), exception);
|
| + if (ret.IsEmpty()) {
|
| + exception = Dart_NewStringFromCString("object must be an Node, ArrayBuffer, Blob, ImageData, or IDBKeyRange");
|
| + goto fail;
|
| + }
|
| + if (exception)
|
| + goto fail;
|
| + ASSERT(ret->IsObject());
|
| + if (scopes.handleJsException(&exception))
|
| + goto fail;
|
| + scopes.setReturnValue(JsObject::toDart(ret.As<v8::Object>()));
|
| + return;
|
| + }
|
| +
|
| +fail:
|
| + Dart_ThrowException(exception);
|
| + ASSERT_NOT_REACHED();
|
| +}
|
| +
|
| +static void applyCallback(Dart_NativeArguments args)
|
| +{
|
| + Dart_Handle exception = 0;
|
| + {
|
| + JsInteropScopes scopes(args);
|
| + DartDOMData* domData = static_cast<DartDOMData*>(Dart_GetNativeIsolateData(args));
|
| + JsFunction* receiver = DartDOMWrapper::receiver<JsFunction>(args);
|
| +
|
| + Vector<v8::Local<v8::Value> > v8Args;
|
| + argsListToV8(domData, Dart_GetNativeArgument(args, 1), &v8Args, exception);
|
| + if (exception)
|
| + goto fail;
|
| +
|
| + v8::Local<v8::Value> thisArg;
|
| + Dart_Handle thisArgDart = Dart_GetNativeArgument(args, 2);
|
| + if (Dart_IsNull(thisArgDart)) {
|
| + // Use the global v8 object if no Dart thisArg was passed in.
|
| + thisArg = DartUtilities::currentV8Context()->Global();
|
| + } else {
|
| + thisArg = JsInterop::fromDart(domData, thisArgDart, exception);
|
| + if (exception)
|
| + goto fail;
|
| + if (!thisArg->IsObject()) {
|
| + exception = Dart_NewStringFromCString("thisArg is not an object");
|
| + goto fail;
|
| + }
|
| + }
|
| +
|
| + v8::Local<v8::Value> ret = V8ScriptRunner::callFunction(receiver->localV8Function(), DartUtilities::scriptExecutionContext(), thisArg.As<v8::Object>(), v8Args.size(), v8Args.data(), v8::Isolate::GetCurrent());
|
| + if (scopes.handleJsException(&exception))
|
| + goto fail;
|
| + scopes.setReturnValue(ret);
|
| + return;
|
| + }
|
| +
|
| +fail:
|
| + Dart_ThrowException(exception);
|
| + ASSERT_NOT_REACHED();
|
| +}
|
| +
|
| +static void applyDebuggerOnlyCallback(Dart_NativeArguments args)
|
| +{
|
| + Dart_Handle exception = 0;
|
| + {
|
| + JsInteropScopes scopes(args);
|
| + DartDOMData* domData = static_cast<DartDOMData*>(Dart_GetNativeIsolateData(args));
|
| + JsFunction* receiver = DartDOMWrapper::receiver<JsFunction>(args);
|
| +
|
| + Vector<v8::Local<v8::Value> > v8Args;
|
| + argsListToV8DebuggerOnly(domData, Dart_GetNativeArgument(args, 1), &v8Args, exception);
|
| + if (exception)
|
| + goto fail;
|
| +
|
| + v8::Local<v8::Value> thisArg;
|
| + Dart_Handle thisArgDart = Dart_GetNativeArgument(args, 2);
|
| + if (Dart_IsNull(thisArgDart)) {
|
| + // Use the global v8 object if no Dart thisArg was passed in.
|
| + thisArg = DartUtilities::currentV8Context()->Global();
|
| + } else {
|
| + thisArg = JsInterop::fromDart(domData, thisArgDart, exception);
|
| + if (exception)
|
| + goto fail;
|
| + if (!thisArg->IsObject()) {
|
| + exception = Dart_NewStringFromCString("thisArg is not an object");
|
| + goto fail;
|
| + }
|
| + }
|
| +
|
| + v8::Local<v8::Value> ret = V8ScriptRunner::callFunction(receiver->localV8Function(), DartUtilities::scriptExecutionContext(), thisArg.As<v8::Object>(), v8Args.size(), v8Args.data(), v8::Isolate::GetCurrent());
|
| + if (scopes.handleJsException(&exception))
|
| + goto fail;
|
| + scopes.setReturnValue(ret);
|
| + return;
|
| + }
|
| +
|
| +fail:
|
| + Dart_ThrowException(exception);
|
| + ASSERT_NOT_REACHED();
|
| +}
|
| +
|
| +static void toStringCallback(Dart_NativeArguments args)
|
| +{
|
| + Dart_Handle exception = 0;
|
| + {
|
| + JsInteropScopes scopes(args);
|
| + JsObject* receiver = DartDOMWrapper::receiver<JsObject>(args);
|
| + v8::Local<v8::Object> v8Object = receiver->localV8Object();
|
| + if (scopes.handleJsException(&exception))
|
| + goto fail;
|
| + if (v8Object.IsEmpty()) {
|
| + exception = Dart_NewStringFromCString("Invalid v8 handle");
|
| + goto fail;
|
| + }
|
| +
|
| + v8::Local<v8::String> v8String = v8Object->ToString();
|
| + if (scopes.handleJsException(&exception))
|
| + goto fail;
|
| + scopes.setReturnValue(v8String);
|
| + return;
|
| + }
|
| +fail:
|
| + Dart_ThrowException(exception);
|
| + ASSERT_NOT_REACHED();
|
| +}
|
| +
|
| +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()));
|
| +}
|
| +
|
| +v8::Handle<v8::Value> mapToV8(DartDOMData* domData, Dart_Handle value, DartHandleToV8Map& map, Dart_Handle& exception)
|
| +{
|
| + Dart_Handle asList = DartUtilities::invokeUtilsMethod("convertMapToList", 1, &value);
|
| + if (!DartUtilities::checkResult(asList, exception))
|
| + return v8::Handle<v8::Value>();
|
| + ASSERT(Dart_IsList(asList));
|
| +
|
| + // Now we have a list [key, value, key, value, ....], create a v8 object and set necesary
|
| + // properties on it.
|
| + v8::Handle<v8::Object> object = v8::Object::New(v8::Isolate::GetCurrent());
|
| + map.set(value, object);
|
| +
|
| + // We converted to internal Dart list, methods shouldn't throw exceptions now.
|
| + intptr_t length = 0;
|
| + Dart_Handle ALLOW_UNUSED result = Dart_ListLength(asList, &length);
|
| + ASSERT(!Dart_IsError(result));
|
| + ASSERT(!(length % 2));
|
| + for (intptr_t i = 0; i < length; i += 2) {
|
| + v8::Handle<v8::Value> key = jsifyHelper(domData, Dart_ListGetAt(asList, i), map, exception);
|
| + if (exception)
|
| + return v8::Handle<v8::Value>();
|
| + v8::Handle<v8::Value> value = jsifyHelper(domData, Dart_ListGetAt(asList, i + 1), map, exception);
|
| + if (exception)
|
| + return v8::Handle<v8::Value>();
|
| +
|
| + object->Set(key, value);
|
| + }
|
| +
|
| + return object;
|
| +}
|
| +
|
| +v8::Handle<v8::Value> listToV8(DartDOMData* domData, Dart_Handle value, DartHandleToV8Map& map, Dart_Handle& exception)
|
| +{
|
| + ASSERT(Dart_IsList(value));
|
| +
|
| + intptr_t length = 0;
|
| + Dart_Handle result = Dart_ListLength(value, &length);
|
| + if (!DartUtilities::checkResult(result, exception))
|
| + return v8::Handle<v8::Value>();
|
| +
|
| + v8::Local<v8::Array> array = v8::Array::New(v8::Isolate::GetCurrent(), length);
|
| + map.set(value, array);
|
| +
|
| + for (intptr_t i = 0; i < length; ++i) {
|
| + result = Dart_ListGetAt(value, i);
|
| + if (!DartUtilities::checkResult(result, exception))
|
| + return v8::Handle<v8::Value>();
|
| + v8::Handle<v8::Value> v8value = jsifyHelper(domData, result, map, exception);
|
| + if (exception)
|
| + return v8::Handle<v8::Value>();
|
| + array->Set(i, v8value);
|
| + }
|
| +
|
| + return array;
|
| +}
|
| +
|
| +v8::Handle<v8::Value> jsifyHelper(DartDOMData* domData, Dart_Handle value, DartHandleToV8Map& map, Dart_Handle& exception)
|
| +{
|
| + DartHandleToV8Map::iterator iter = map.find(value);
|
| + if (iter != map.end())
|
| + return iter->value;
|
| +
|
| + if (Dart_IsList(value))
|
| + return listToV8(domData, value, map, exception);
|
| +
|
| + bool isMap = DartUtilities::dartToBool(DartUtilities::invokeUtilsMethod("isMap", 1, &value), exception);
|
| + ASSERT(!exception);
|
| + if (isMap)
|
| + return mapToV8(domData, value, map, exception);
|
| +
|
| + Dart_Handle maybeList = DartUtilities::invokeUtilsMethod("toListIfIterable", 1, &value);
|
| + if (Dart_IsList(maybeList))
|
| + return listToV8(domData, maybeList, map, exception);
|
| +
|
| + v8::Handle<v8::Value> ret = JsInterop::fromDart(domData, value, exception);
|
| + map.set(value, ret);
|
| + return ret;
|
| +}
|
| +
|
| +static void jsifyCallback(Dart_NativeArguments args)
|
| +{
|
| + Dart_Handle exception = 0;
|
| + {
|
| + JsInteropScopes scopes(args);
|
| + Dart_Handle value = Dart_GetNativeArgument(args, 0);
|
| + DartDOMData* domData = static_cast<DartDOMData*>(Dart_GetNativeIsolateData(args));
|
| + DartHandleToV8Map map;
|
| + v8::Local<v8::Value> ret = jsifyHelper(domData, value, map, exception);
|
| + if (exception)
|
| + goto fail;
|
| +
|
| + if (scopes.handleJsException(&exception))
|
| + goto fail;
|
| + // Intentionally skip auto-conversion in this case as the user expects
|
| + // 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>()));
|
| + } else {
|
| + // This will throw an exception in Dart checked mode.
|
| + scopes.setReturnValue(ret);
|
| + }
|
| + return;
|
| + }
|
| +fail:
|
| + Dart_ThrowException(exception);
|
| + ASSERT_NOT_REACHED();
|
| +}
|
| +
|
| +static void withThisCallback(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 = dartFunctionTemplate()->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[] = {
|
| + { JsInteropInternal::jsObjectConstructorCallback, 2, "JsObject_constructorCallback" },
|
| + { JsInteropInternal::contextCallback, 0, "Js_context_Callback" },
|
| + { JsInteropInternal::jsifyCallback, 1, "JsObject_jsify" },
|
| + { JsInteropInternal::withThisCallback, 1, "JsFunction_withThis" },
|
| + { JsInteropInternal::getterCallback, 2, "JsObject_[]" },
|
| + { JsInteropInternal::setterCallback, 3, "JsObject_[]=" },
|
| + { JsInteropInternal::hashCodeCallback, 1, "JsObject_hashCode" },
|
| + { JsInteropInternal::callMethodCallback, 3, "JsObject_callMethod" },
|
| + { JsInteropInternal::toStringCallback, 1, "JsObject_toString" },
|
| + { JsInteropInternal::identityEqualityCallback, 2, "JsObject_identityEquality" },
|
| + { JsInteropInternal::hasPropertyCallback, 2, "JsObject_hasProperty" },
|
| + { JsInteropInternal::deletePropertyCallback, 2, "JsObject_deleteProperty" },
|
| + { JsInteropInternal::instanceofCallback, 2, "JsObject_instanceof" },
|
| + { JsInteropInternal::applyCallback, 3, "JsFunction_apply" },
|
| + { JsInteropInternal::applyDebuggerOnlyCallback, 3, "JsFunction_applyDebuggerOnly" },
|
| + { JsInteropInternal::newJsArrayCallback, 0, "JsArray_newJsArray" },
|
| + { JsInteropInternal::newJsArrayFromSafeListCallback, 1, "JsArray_newJsArrayFromSafeList" },
|
| + { JsInteropInternal::jsArrayLengthCallback, 1, "JsArray_length" },
|
| + { JsInteropInternal::fromBrowserObjectCallback, 1, "JsObject_fromBrowserObject" },
|
| + { 0, 0, 0 },
|
| +};
|
| +
|
| +Dart_NativeFunction JsInterop::resolver(Dart_Handle nameHandle, int argumentCount, bool* autoSetupScope)
|
| +{
|
| + ASSERT(autoSetupScope);
|
| + *autoSetupScope = true;
|
| + String name = DartUtilities::toString(nameHandle);
|
| +
|
| + for (intptr_t i = 0; nativeEntries[i].nativeFunction != 0; i++) {
|
| + if (argumentCount == nativeEntries[i].argumentCount && name == nativeEntries[i].name) {
|
| + return nativeEntries[i].nativeFunction;
|
| + }
|
| + }
|
| +
|
| + return 0;
|
| +}
|
| +
|
| +const uint8_t* JsInterop::symbolizer(Dart_NativeFunction nf)
|
| +{
|
| + for (intptr_t i = 0; nativeEntries[i].nativeFunction != 0; i++) {
|
| + if (nf == nativeEntries[i].nativeFunction) {
|
| + return reinterpret_cast<const uint8_t*>(nativeEntries[i].name);
|
| + }
|
| + }
|
| + return 0;
|
| +}
|
| +
|
| +}
|
|
|