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;
    }
    void VisitPersistentHandle(v8::Persistent<v8::Value>* value, uint16_t classId) override
    {
        if (classId != WrapperTypeInfo::NodeClassId && classId != WrapperTypeInfo::ObjectClassId)
            return;

        const v8::Persistent<v8::Object>& wrapper = v8::Persistent<v8::Object>::Cast(*value);

        if (m_visitor)
            toWrapperTypeInfo(wrapper)->trace(m_visitor, toScriptWrappable(wrapper));
    }
bool V8DOMWrapper::hasInternalFieldsSet(v8::Local<v8::Value> value)
{
    if (value.IsEmpty() || !value->IsObject())
        return false;
    v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(value);

    if (object->InternalFieldCount() < v8DefaultWrapperInternalFieldCount)
        return false;

    const ScriptWrappable* untrustedScriptWrappable = toScriptWrappable(object);
    const WrapperTypeInfo* untrustedWrapperTypeInfo = toWrapperTypeInfo(object);
    return untrustedScriptWrappable
        && untrustedWrapperTypeInfo
        && untrustedWrapperTypeInfo->ginEmbedder == gin::kEmbedderBlink;
}
    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();
        }
    }
Esempio n. 5
0
        virtual void VisitPersistentHandle(v8::Persistent<v8::Value>* value, uint16_t classId) override
        {
            if (classId != WrapperTypeInfo::NodeClassId)
                return;

#if ENABLE(ASSERT)
            {
                v8::HandleScope scope(m_isolate);
                v8::Local<v8::Object> wrapper = v8::Local<v8::Object>::New(m_isolate, v8::Persistent<v8::Object>::Cast(*value));
                ASSERT(V8Node::hasInstance(wrapper, m_isolate));
                ASSERT(wrapper->IsObject());
            }
#endif
            m_visitor->visitNode(toScriptWrappable(v8::Persistent<v8::Object>::Cast(*value))->toImpl<Node>());
        }
    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;
            }
        }
    }
TestArrayBuffer* V8ArrayBuffer::toImpl(v8::Local<v8::Object> object)
{
    ASSERT(object->IsArrayBuffer());
    v8::Local<v8::ArrayBuffer> v8buffer = object.As<v8::ArrayBuffer>();
    if (v8buffer->IsExternal()) {
        const WrapperTypeInfo* wrapperTypeInfo = toWrapperTypeInfo(object);
        RELEASE_ASSERT(wrapperTypeInfo);
        RELEASE_ASSERT(wrapperTypeInfo->ginEmbedder == gin::kEmbedderBlink);
        return toScriptWrappable(object)->toImpl<TestArrayBuffer>();
    }

    // Transfer the ownership of the allocated memory to an ArrayBuffer without
    // copying.
    v8::ArrayBuffer::Contents v8Contents = v8buffer->Externalize();
    WTF::ArrayBufferContents contents(v8Contents.Data(), v8Contents.ByteLength(), WTF::ArrayBufferContents::NotShared);
    TestArrayBuffer* buffer = TestArrayBuffer::create(contents);
    v8::Local<v8::Object> associatedWrapper = buffer->associateWithWrapper(v8::Isolate::GetCurrent(), buffer->wrapperTypeInfo(), object);
    ASSERT_UNUSED(associatedWrapper, associatedWrapper == object);

    return buffer;
}
TestUint8ClampedArray* V8Uint8ClampedArray::toImpl(v8::Local<v8::Object> object)
{
    ASSERT(object->IsUint8ClampedArray());
    ScriptWrappable* scriptWrappable = toScriptWrappable(object);
    if (scriptWrappable)
        return scriptWrappable->toImpl<TestUint8ClampedArray>();

    v8::Local<v8::Uint8ClampedArray> v8View = object.As<v8::Uint8ClampedArray>();
    v8::Local<v8::Object> arrayBuffer = v8View->Buffer();
    RefPtr<TestUint8ClampedArray> typedArray;
    if (arrayBuffer->IsArrayBuffer()) {
        typedArray = TestUint8ClampedArray::create(V8ArrayBuffer::toImpl(arrayBuffer), v8View->ByteOffset(), v8View->Length());
    } else if (arrayBuffer->IsSharedArrayBuffer()) {
        typedArray = TestUint8ClampedArray::create(V8SharedArrayBuffer::toImpl(arrayBuffer), v8View->ByteOffset(), v8View->Length());
    } else {
        ASSERT_NOT_REACHED();
    }
    v8::Local<v8::Object> associatedWrapper = typedArray->associateWithWrapper(v8::Isolate::GetCurrent(), typedArray->wrapperTypeInfo(), object);
    ASSERT_UNUSED(associatedWrapper, associatedWrapper == object);

    return typedArray->toImpl<TestUint8ClampedArray>();
}
Esempio n. 9
0
EventTarget* WrapperTypeInfo::toEventTarget(v8::Handle<v8::Object> object) const
{
    if (eventTargetInheritance == NotInheritFromEventTarget)
        return 0;
    return static_cast<EventTarget*>(toScriptWrappable(object));
}