void VisitPersistentHandle(v8::Persistent<v8::Value>* value, uint16_t classId) override
    {
        // If we have already found any wrapper that has a pending activity,
        // we don't need to check other wrappers.
        if (m_pendingActivityFound)
            return;

        if (classId != WrapperTypeInfo::NodeClassId && classId != WrapperTypeInfo::ObjectClassId)
            return;

        const v8::Persistent<v8::Object>& wrapper = v8::Persistent<v8::Object>::Cast(*value);
        const WrapperTypeInfo* type = toWrapperTypeInfo(wrapper);
        // The ExecutionContext check is heavy, so it should be done at the last.
        if (type != npObjectTypeInfo()
            && toScriptWrappable(wrapper)->hasPendingActivity()
            // TODO(haraken): Currently we don't have a way to get a creation
            // context from a wrapper. We should implement the way and enable
            // the following condition.
            //
            // This condition affects only compositor workers, where one isolate
            // is shared by multiple workers. If we don't have the condition,
            // a worker object for a compositor worker doesn't get collected
            // until all compositor workers in the same isolate lose pending
            // activities. In other words, not having the condition delays
            // destruction of a worker object of a compositor worker.
            //
            /* && toExecutionContext(wrapper->creationContext()) == m_executionContext */
            )
            m_pendingActivityFound = true;
    }
Example #2
0
bool isWrappedNPObject(v8::Handle<v8::Object> object)
{
    if (object->InternalFieldCount() == npObjectInternalFieldCount) {
        const WrapperTypeInfo* typeInfo = static_cast<const WrapperTypeInfo*>(object->GetAlignedPointerFromInternalField(v8DOMWrapperTypeIndex));
        return typeInfo == npObjectTypeInfo();
    }
    return false;
}
void forgetV8ObjectForNPObject(NPObject* object)
{
    v8::Isolate* isolate = v8::Isolate::GetCurrent();
    v8::HandleScope scope(isolate);
    v8::Handle<v8::Object> wrapper = staticNPObjectMap().getNewLocal(isolate, object);
    if (!wrapper.IsEmpty()) {
        V8DOMWrapper::clearNativeInfo(wrapper, npObjectTypeInfo());
        staticNPObjectMap().removeAndDispose(object);
        _NPN_ReleaseObject(object);
    }
}
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;
}
    void VisitPersistentHandle(v8::Persistent<v8::Value>* value, uint16_t classId) override
    {

        if (classId != WrapperTypeInfo::NodeClassId && classId != WrapperTypeInfo::ObjectClassId) {
            return;
        }

        // MinorGC does not collect objects because it may be expensive to
        // update references during minorGC
        if (classId == WrapperTypeInfo::ObjectClassId) {
            v8::Persistent<v8::Object>::Cast(*value).MarkActive();
            return;
        }

        v8::Local<v8::Object> wrapper = v8::Local<v8::Object>::New(m_isolate, v8::Persistent<v8::Object>::Cast(*value));
        ASSERT(V8DOMWrapper::hasInternalFieldsSet(wrapper));
        const WrapperTypeInfo* type = toWrapperTypeInfo(wrapper);
        if (type != npObjectTypeInfo() && toScriptWrappable(wrapper)->hasPendingActivity()) {
            v8::Persistent<v8::Object>::Cast(*value).MarkActive();
            return;
        }

        if (classId == WrapperTypeInfo::NodeClassId) {
            ASSERT(V8Node::hasInstance(wrapper, m_isolate));
            Node* node = V8Node::toImpl(wrapper);
            if (node->hasEventListeners()) {
                v8::Persistent<v8::Object>::Cast(*value).MarkActive();
                return;
            }
            // FIXME: Remove the special handling for image elements.
            // The same special handling is in V8GCController::opaqueRootForGC().
            // Maybe should image elements be active DOM nodes?
            // See https://code.google.com/p/chromium/issues/detail?id=164882
            if (isHTMLImageElement(*node) && toHTMLImageElement(*node).hasPendingActivity()) {
                v8::Persistent<v8::Object>::Cast(*value).MarkActive();
                return;
            }
            // FIXME: Remove the special handling for SVG elements.
            // We currently can't collect SVG Elements from minor gc, as we have
            // strong references from SVG property tear-offs keeping context SVG element alive.
            if (node->isSVGElement()) {
                v8::Persistent<v8::Object>::Cast(*value).MarkActive();
                return;
            }
        }
    }
Example #6
0
NPObject* npCreateV8ScriptObject(NPP npp, v8::Handle<v8::Object> object, DOMWindow* root, v8::Isolate* isolate)
{
    // Check to see if this object is already wrapped.
    if (object->InternalFieldCount() == npObjectInternalFieldCount) {
        const WrapperTypeInfo* typeInfo = static_cast<const WrapperTypeInfo*>(object->GetAlignedPointerFromInternalField(v8DOMWrapperTypeIndex));
        if (typeInfo == npObjectTypeInfo()) {
            NPObject* returnValue = v8ObjectToNPObject(object);
            _NPN_RetainObject(returnValue);
            return returnValue;
        }
    }

    V8NPObjectVector* objectVector = 0;
    if (V8PerContextData* perContextData = V8PerContextData::from(object->CreationContext())) {
        int v8ObjectHash = object->GetIdentityHash();
        ASSERT(v8ObjectHash);
        V8NPObjectMap* v8NPObjectMap = perContextData->v8NPObjectMap();
        V8NPObjectMap::iterator iter = v8NPObjectMap->find(v8ObjectHash);
        if (iter != v8NPObjectMap->end()) {
            V8NPObjectVector& objects = iter->value;
            for (size_t index = 0; index < objects.size(); ++index) {
                V8NPObject* v8npObject = objects.at(index);
                if (v8npObject->v8Object == object && v8npObject->rootObject == root) {
                    _NPN_RetainObject(&v8npObject->object);
                    return reinterpret_cast<NPObject*>(v8npObject);
                }
            }
        } else {
            iter = v8NPObjectMap->set(v8ObjectHash, V8NPObjectVector()).iterator;
        }
        objectVector = &iter->value;
    }

    V8NPObject* v8npObject = reinterpret_cast<V8NPObject*>(_NPN_CreateObject(npp, &V8NPObjectClass));
    // This is uninitialized memory, we need to clear it so that
    // Persistent::Reset won't try to Dispose anything bogus.
    v8npObject->v8Object.Clear();
    v8npObject->v8Object.Reset(isolate, object);
    v8npObject->rootObject = root;

    if (objectVector)
        objectVector->append(v8npObject);

    return reinterpret_cast<NPObject*>(v8npObject);
}
Example #7
0
NPObject* npCreateV8ScriptObject(NPP npp, v8::Handle<v8::Object> object, DOMWindow* root)
{
    // Check to see if this object is already wrapped.
    if (object->InternalFieldCount() == npObjectInternalFieldCount) {
        WrapperTypeInfo* typeInfo = static_cast<WrapperTypeInfo*>(object->GetAlignedPointerFromInternalField(v8DOMWrapperTypeIndex));
        if (typeInfo == npObjectTypeInfo()) {

            NPObject* returnValue = v8ObjectToNPObject(object);
            _NPN_RetainObject(returnValue);
            return returnValue;
        }
    }

    V8NPObjectVector* objectVector = 0;
    if (V8PerContextData* perContextData = V8PerContextData::from(object->CreationContext())) {
        int v8ObjectHash = object->GetIdentityHash();
        ASSERT(v8ObjectHash);
        V8NPObjectMap* v8NPObjectMap = perContextData->v8NPObjectMap();
        V8NPObjectMap::iterator iter = v8NPObjectMap->find(v8ObjectHash);
        if (iter != v8NPObjectMap->end()) {
            V8NPObjectVector& objects = iter->value;
            for (size_t index = 0; index < objects.size(); ++index) {
                V8NPObject* v8npObject = objects.at(index);
                if (v8npObject->v8Object == object && v8npObject->rootObject == root) {
                    _NPN_RetainObject(&v8npObject->object);
                    return reinterpret_cast<NPObject*>(v8npObject);
                }
            }
        } else {
            iter = v8NPObjectMap->set(v8ObjectHash, V8NPObjectVector()).iterator;
        }
        objectVector = &iter->value;
    }
    V8NPObject* v8npObject = reinterpret_cast<V8NPObject*>(_NPN_CreateObject(npp, &V8NPObjectClass));
    v8npObject->v8Object = v8::Persistent<v8::Object>::New(v8::Isolate::GetCurrent(), object);
    v8npObject->rootObject = root;

    if (objectVector)
        objectVector->append(v8npObject);

    return reinterpret_cast<NPObject*>(v8npObject);
}
Example #8
0
NPObject* npCreateV8ScriptObject(NPP npp, v8::Handle<v8::Object> object, DOMWindow* root)
{
    // Check to see if this object is already wrapped.
    if (object->InternalFieldCount() == npObjectInternalFieldCount) {
        WrapperTypeInfo* typeInfo = static_cast<WrapperTypeInfo*>(object->GetPointerFromInternalField(v8DOMWrapperTypeIndex));
        if (typeInfo == npObjectTypeInfo()) {

            NPObject* returnValue = v8ObjectToNPObject(object);
            _NPN_RetainObject(returnValue);
            return returnValue;
        }
    }

    V8NPObject* v8npObject = reinterpret_cast<V8NPObject*>(_NPN_CreateObject(npp, &V8NPObjectClass));
    v8npObject->v8Object = v8::Persistent<v8::Object>::New(object);
#ifndef NDEBUG
    V8GCController::registerGlobalHandle(NPOBJECT, v8npObject, v8npObject->v8Object);
#endif
    v8npObject->rootObject = root;
    return reinterpret_cast<NPObject*>(v8npObject);
}
    void VisitPersistentHandle(v8::Persistent<v8::Value>* value, uint16_t classId) override
    {
        if (classId != WrapperTypeInfo::NodeClassId && classId != WrapperTypeInfo::ObjectClassId)
            return;

        v8::Local<v8::Object> wrapper = v8::Local<v8::Object>::New(m_isolate, v8::Persistent<v8::Object>::Cast(*value));
        ASSERT(V8DOMWrapper::hasInternalFieldsSet(wrapper));

        const WrapperTypeInfo* type = toWrapperTypeInfo(wrapper);
        if (type != npObjectTypeInfo() && toScriptWrappable(wrapper)->hasPendingActivity()) {
            // If you hit this assert, you'll need to add a [DependentiLifetime]
            // extended attribute to the DOM interface. A DOM interface that
            // overrides hasPendingActivity must be marked as [DependentiLifetime].
            RELEASE_ASSERT(!value->IsIndependent());
            m_isolate->SetObjectGroupId(*value, liveRootId());
            ++m_domObjectsWithPendingActivity;
        }

        if (value->IsIndependent())
            return;

        if (classId == WrapperTypeInfo::NodeClassId) {
            ASSERT(V8Node::hasInstance(wrapper, m_isolate));
            Node* node = V8Node::toImpl(wrapper);
            if (node->hasEventListeners())
                addReferencesForNodeWithEventListeners(m_isolate, node, v8::Persistent<v8::Object>::Cast(*value));
            Node* root = V8GCController::opaqueRootForGC(m_isolate, node);
            m_isolate->SetObjectGroupId(*value, v8::UniqueId(reinterpret_cast<intptr_t>(root)));
            if (m_constructRetainedObjectInfos)
                m_groupsWhichNeedRetainerInfo.append(root);
        } else if (classId == WrapperTypeInfo::ObjectClassId) {
            type->visitDOMWrapper(m_isolate, toScriptWrappable(wrapper), v8::Persistent<v8::Object>::Cast(*value));
        } else {
            ASSERT_NOT_REACHED();
        }
    }