Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "bindings/core/v8/ScriptCustomElementDefinition.h" | |
| 6 | |
| 7 #include "bindings/core/v8/ScriptState.h" | |
| 8 #include "bindings/core/v8/V8CustomElementsRegistry.h" | |
| 9 #include "bindings/core/v8/V8HiddenValue.h" | |
| 10 #include "bindings/core/v8/V8PerContextData.h" | |
| 11 #include "core/frame/LocalDOMWindow.h" | |
| 12 #include "v8.h" | |
| 13 #include "wtf/Allocator.h" | |
| 14 #include "wtf/Noncopyable.h" | |
| 15 | |
| 16 namespace blink { | |
| 17 | |
| 18 // Custom elements stores state off the registry's wrapper. To avoid leaking | |
| 19 // contexts, that state should be manipulated in the registry's wrapper | |
| 20 // context. This helper retrieves the wrapper and enters its context. | |
| 21 class RegistryScriptStateScope { | |
| 22 STACK_ALLOCATED(); | |
| 23 WTF_MAKE_NONCOPYABLE(RegistryScriptStateScope); | |
| 24 public: | |
| 25 RegistryScriptStateScope( | |
| 26 ScriptState* current, | |
| 27 CustomElementsRegistry* registry) | |
| 28 : m_registry(toV8(registry, current).As<v8::Object>()) | |
| 29 , m_scriptState(ScriptState::from(m_registry->CreationContext())) | |
|
Yuki
2016/05/26 07:48:40
What script state are you expecting here? It's th
dominicc (has gone to gerrit)
2016/05/27 04:54:17
OK, added some examples.
| |
| 30 , m_scope(m_scriptState) | |
| 31 { | |
| 32 CHECK(current->world().isMainWorld()); | |
| 33 } | |
| 34 | |
| 35 ScriptState* scriptState() const { return m_scriptState; } | |
| 36 ScriptState* operator->() const { return m_scriptState; } | |
| 37 const v8::Local<v8::Object>& wrapper() const { return m_registry; } | |
| 38 | |
| 39 private: | |
| 40 v8::Local<v8::Object> m_registry; | |
| 41 ScriptState* m_scriptState; | |
| 42 ScriptState::Scope m_scope; | |
| 43 }; | |
| 44 | |
| 45 // Retrieves the custom elements constructor -> ID map, creating it if | |
| 46 // necessary. The same map is used to keep prototypes alive. | |
| 47 static v8::Local<v8::Map> ensureCustomElementsRegistryMap( | |
| 48 RegistryScriptStateScope& scope) | |
| 49 { | |
| 50 v8::Local<v8::String> name = V8HiddenValue::customElementsRegistryMap( | |
| 51 scope->isolate()); | |
| 52 v8::Local<v8::Value> map = V8HiddenValue::getHiddenValue( | |
| 53 scope.scriptState(), | |
| 54 scope.wrapper(), | |
| 55 name); | |
| 56 if (map.IsEmpty()) { | |
| 57 map = v8::Map::New(scope->isolate()); | |
| 58 V8HiddenValue::setHiddenValue( | |
| 59 scope.scriptState(), | |
| 60 scope.wrapper(), | |
| 61 name, | |
| 62 map); | |
| 63 } | |
| 64 return map.As<v8::Map>(); | |
| 65 } | |
| 66 | |
| 67 ScriptCustomElementDefinition* ScriptCustomElementDefinition::forConstructor( | |
| 68 ScriptState* scriptState, | |
| 69 CustomElementsRegistry* registry, | |
| 70 const v8::Local<v8::Value>& constructor) | |
| 71 { | |
| 72 if (!scriptState->contextIsValid()) | |
| 73 return nullptr; | |
| 74 RegistryScriptStateScope scope(scriptState, registry); | |
|
haraken
2016/05/26 08:33:46
Why do you need to enter ScriptState's scope here?
dominicc (has gone to gerrit)
2016/05/27 04:54:17
When the HTMLElement constructor uses forConstruct
| |
| 75 v8::Local<v8::Map> map = ensureCustomElementsRegistryMap(scope); | |
| 76 v8::Local<v8::Value> entry = v8CallOrCrash( | |
| 77 map->Get(scope->context(), constructor)); | |
| 78 if (!entry->IsUint32()) | |
| 79 return nullptr; | |
| 80 uint32_t id = v8CallOrCrash(entry->Uint32Value(scope->context())); | |
| 81 if (V8PerContextData* perContextData = scope->perContextData()) | |
| 82 return perContextData->customElements()->getDefinition(id); | |
| 83 return nullptr; | |
| 84 } | |
| 85 | |
| 86 ScriptCustomElementDefinition* ScriptCustomElementDefinition::create( | |
| 87 ScriptState* scriptState, | |
| 88 CustomElementsRegistry* registry, | |
| 89 const CustomElementDescriptor& descriptor, | |
| 90 const v8::Local<v8::Object>& constructor, | |
| 91 const v8::Local<v8::Object>& prototype) | |
| 92 { | |
| 93 ScriptCustomElementDefinition* def = new ScriptCustomElementDefinition( | |
| 94 scriptState, | |
| 95 descriptor, | |
| 96 constructor, | |
| 97 prototype); | |
| 98 | |
| 99 RegistryScriptStateScope scope(scriptState, registry); | |
| 100 V8PerContextData* perContextData = scope->perContextData(); | |
| 101 if (!perContextData) | |
| 102 return nullptr; | |
| 103 uint32_t id = perContextData->customElements()->addDefinition(def); | |
| 104 | |
| 105 // Add a constructor -> ID mapping to the registry. | |
| 106 v8::Local<v8::Value> idValue = | |
| 107 v8::Integer::NewFromUnsigned(scope->isolate(), id); | |
| 108 v8::Local<v8::Map> map = ensureCustomElementsRegistryMap(scope); | |
| 109 v8CallOrCrash(map->Set(scope->context(), constructor, idValue)); | |
| 110 v8CallOrCrash(map->Set(scope->context(), idValue, prototype)); | |
| 111 | |
| 112 return def; | |
| 113 } | |
| 114 | |
| 115 ScriptCustomElementDefinition::ScriptCustomElementDefinition( | |
| 116 ScriptState* scriptState, | |
| 117 const CustomElementDescriptor& descriptor, | |
| 118 const v8::Local<v8::Object>& constructor, | |
| 119 const v8::Local<v8::Object>& prototype) | |
| 120 : CustomElementDefinition(descriptor) | |
| 121 , m_constructor(scriptState->isolate(), constructor) | |
| 122 , m_prototype(scriptState->isolate(), prototype) | |
| 123 { | |
| 124 // These objects are kept alive by references from the | |
| 125 // CustomElementsRegistry wrapper set up by | |
| 126 // ScriptCustomElementDefinition::create. | |
| 127 m_constructor.setPhantom(); | |
| 128 m_prototype.setPhantom(); | |
| 129 } | |
| 130 | |
| 131 v8::Local<v8::Object> ScriptCustomElementDefinition::constructor( | |
| 132 ScriptState* scriptState) const | |
| 133 { | |
| 134 DCHECK(!m_constructor.isEmpty()); | |
| 135 return m_constructor.newLocal(scriptState->isolate()); | |
| 136 } | |
| 137 | |
| 138 v8::Local<v8::Object> ScriptCustomElementDefinition::prototype( | |
| 139 ScriptState* scriptState) const | |
| 140 { | |
| 141 DCHECK(!m_prototype.isEmpty()); | |
| 142 return m_prototype.newLocal(scriptState->isolate()); | |
| 143 } | |
| 144 | |
| 145 } // namespace blink | |
| OLD | NEW |