v8::Handle<v8::Value> convertNPVariantToV8Object(const NPVariant* variant, NPObject* owner, v8::Isolate* isolate) { NPVariantType type = variant->type; switch (type) { case NPVariantType_Int32: return v8::Integer::New(NPVARIANT_TO_INT32(*variant), isolate); case NPVariantType_Double: return v8::Number::New(isolate, NPVARIANT_TO_DOUBLE(*variant)); case NPVariantType_Bool: return v8Boolean(NPVARIANT_TO_BOOLEAN(*variant), isolate); case NPVariantType_Null: return v8::Null(isolate); case NPVariantType_Void: return v8::Undefined(isolate); case NPVariantType_String: { NPString src = NPVARIANT_TO_STRING(*variant); return v8::String::NewFromUtf8(isolate, src.UTF8Characters, v8::String::kNormalString, src.UTF8Length); } case NPVariantType_Object: { NPObject* object = NPVARIANT_TO_OBJECT(*variant); if (V8NPObject* v8Object = npObjectToV8NPObject(object)) return v8::Local<v8::Object>::New(isolate, v8Object->v8Object); return createV8ObjectForNPObject(object, owner, isolate); } default: return v8::Undefined(isolate); } }
void disposeUnderlyingV8Object(NPObject* npObject, v8::Isolate* isolate) { ASSERT(npObject); V8NPObject* v8NpObject = npObjectToV8NPObject(npObject); if (!v8NpObject) return; v8::HandleScope scope(isolate); v8::Handle<v8::Object> v8Object = v8::Local<v8::Object>::New(isolate, v8NpObject->v8Object); ASSERT(!v8Object->CreationContext().IsEmpty()); if (V8PerContextData* perContextData = V8PerContextData::from(v8Object->CreationContext())) { V8NPObjectMap* v8NPObjectMap = perContextData->v8NPObjectMap(); int v8ObjectHash = v8Object->GetIdentityHash(); ASSERT(v8ObjectHash); V8NPObjectMap::iterator iter = v8NPObjectMap->find(v8ObjectHash); if (iter != v8NPObjectMap->end()) { V8NPObjectVector& objects = iter->value; for (size_t index = 0; index < objects.size(); ++index) { if (objects.at(index) == v8NpObject) { objects.remove(index); break; } } if (objects.isEmpty()) v8NPObjectMap->remove(v8ObjectHash); } } v8NpObject->v8Object.Dispose(); v8NpObject->v8Object.Clear(); v8NpObject->rootObject = 0; }
v8::Local<v8::Object> createV8ObjectForNPObject(NPObject* object, NPObject* root) { static v8::Persistent<v8::FunctionTemplate> npObjectDesc; ASSERT(v8::Context::InContext()); v8::Isolate* isolate = v8::Isolate::GetCurrent(); // If this is a v8 object, just return it. V8NPObject* v8NPObject = npObjectToV8NPObject(object); if (v8NPObject) return v8::Local<v8::Object>::New(isolate, v8NPObject->v8Object); // If we've already wrapped this object, just return it. v8::Handle<v8::Object> wrapper = staticNPObjectMap().get(object); if (!wrapper.IsEmpty()) return v8::Local<v8::Object>::New(isolate, wrapper); // FIXME: we should create a Wrapper type as a subclass of JSObject. It has two internal fields, field 0 is the wrapped // pointer, and field 1 is the type. There should be an api function that returns unused type id. The same Wrapper type // can be used by DOM bindings. if (npObjectDesc.IsEmpty()) { v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(); templ->InstanceTemplate()->SetInternalFieldCount(npObjectInternalFieldCount); templ->InstanceTemplate()->SetNamedPropertyHandler(npObjectNamedPropertyGetter, npObjectNamedPropertySetter, npObjectQueryProperty, 0, npObjectNamedPropertyEnumerator); templ->InstanceTemplate()->SetIndexedPropertyHandler(npObjectIndexedPropertyGetter, npObjectIndexedPropertySetter, 0, 0, npObjectIndexedPropertyEnumerator); templ->InstanceTemplate()->SetCallAsFunctionHandler(npObjectInvokeDefaultHandler); npObjectDesc.Reset(isolate, templ); } // FIXME: Move staticNPObjectMap() to DOMDataStore. // Use V8DOMWrapper::createWrapper() and // V8DOMWrapper::associateObjectWithWrapper() // to create a wrapper object. v8::Handle<v8::Function> v8Function = v8::Local<v8::FunctionTemplate>::New(isolate, npObjectDesc)->GetFunction(); v8::Local<v8::Object> value = V8ObjectConstructor::newInstance(v8Function); if (value.IsEmpty()) return value; V8DOMWrapper::setNativeInfo(value, npObjectTypeInfo(), object); // KJS retains the object as part of its wrapper (see Bindings::CInstance). _NPN_RetainObject(object); _NPN_RegisterObject(object, root); WrapperConfiguration configuration = buildWrapperConfiguration(object, WrapperConfiguration::Dependent); staticNPObjectMap().set(object, value, configuration); ASSERT(V8DOMWrapper::maybeDOMWrapper(value)); return value; }
v8::Local<v8::Value> WebBindings::toV8Value(const NPVariant* variant) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); if (variant->type == NPVariantType_Object) { NPObject* object = NPVARIANT_TO_OBJECT(*variant); V8NPObject* v8Object = npObjectToV8NPObject(object); if (!v8Object) return v8::Undefined(isolate); return convertNPVariantToV8Object(isolate, variant, v8Object->rootObject->frame()->script().windowScriptNPObject()); } // Safe to pass 0 since we have checked the script object class to make sure the // argument is a primitive v8 type. return convertNPVariantToV8Object(isolate, variant, 0); }
static bool getArrayBufferViewImpl(NPObject* object, WebArrayBufferView* arrayBufferView, v8::Isolate* isolate) { if (!object) return false; V8NPObject* v8NPObject = npObjectToV8NPObject(object); if (!v8NPObject) return false; v8::HandleScope handleScope(isolate); v8::Local<v8::Object> v8Object = v8::Local<v8::Object>::New(isolate, v8NPObject->v8Object); if (v8Object.IsEmpty()) return false; DOMArrayBufferView* impl = V8ArrayBufferView::hasInstance(v8Object, isolate) ? V8ArrayBufferView::toImpl(v8Object) : 0; if (!impl) return false; *arrayBufferView = WebArrayBufferView(impl); return true; }
static bool getElementImpl(NPObject* object, WebElement* webElement, v8::Isolate* isolate) { if (!object) return false; V8NPObject* v8NPObject = npObjectToV8NPObject(object); if (!v8NPObject) return false; v8::HandleScope handleScope(isolate); v8::Local<v8::Object> v8Object = v8::Local<v8::Object>::New(isolate, v8NPObject->v8Object); if (v8Object.IsEmpty()) return false; Element* native = V8Element::hasInstance(v8Object, isolate) ? V8Element::toImpl(v8Object) : 0; if (!native) return false; *webElement = WebElement(native); return true; }
static bool getArrayBufferImpl(NPObject* object, WebArrayBuffer* arrayBuffer, v8::Isolate* isolate) { if (!object) return false; V8NPObject* v8NPObject = npObjectToV8NPObject(object); if (!v8NPObject) return false; v8::HandleScope handleScope(isolate); v8::Handle<v8::Object> v8Object = v8::Local<v8::Object>::New(isolate, v8NPObject->v8Object); if (v8Object.IsEmpty()) return false; ArrayBuffer* native = V8ArrayBuffer::hasInstance(v8Object, isolate) ? V8ArrayBuffer::toNative(v8Object) : 0; if (!native) return false; *arrayBuffer = WebArrayBuffer(native); return true; }
static bool getNodeImpl(NPObject* object, WebNode* webNode, v8::Isolate* isolate) { if (!object) return false; V8NPObject* v8NPObject = npObjectToV8NPObject(object); if (!v8NPObject) return false; v8::HandleScope handleScope(isolate); v8::Handle<v8::Object> v8Object = v8::Local<v8::Object>::New(isolate, v8NPObject->v8Object); if (v8Object.IsEmpty()) return false; Node* native = V8Node::hasInstance(v8Object, isolate) ? V8Node::toNative(v8Object) : 0; if (!native) return false; *webNode = WebNode(native); return true; }
static bool getRangeImpl(NPObject* object, WebRange* webRange, v8::Isolate* isolate) { if (!object) return false; V8NPObject* v8NPObject = npObjectToV8NPObject(object); if (!v8NPObject) return false; v8::HandleScope handleScope(isolate); v8::Local<v8::Object> v8Object = v8::Local<v8::Object>::New(isolate, v8NPObject->v8Object); if (v8Object.IsEmpty()) return false; if (!V8Range::wrapperTypeInfo.equals(toWrapperTypeInfo(v8Object))) return false; Range* native = V8Range::hasInstance(v8Object, isolate) ? V8Range::toImpl(v8Object) : 0; if (!native) return false; *webRange = WebRange(native); return true; }