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(); } }
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>(); }
EventTarget* WrapperTypeInfo::toEventTarget(v8::Handle<v8::Object> object) const { if (eventTargetInheritance == NotInheritFromEventTarget) return 0; return static_cast<EventTarget*>(toScriptWrappable(object)); }