| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "bindings/core/v8/ScriptCustomElementDefinition.h" | 5 #include "bindings/core/v8/ScriptCustomElementDefinition.h" |
| 6 | 6 |
| 7 #include "bindings/core/v8/ScriptState.h" | 7 #include "bindings/core/v8/ScriptState.h" |
| 8 #include "bindings/core/v8/V8Binding.h" | 8 #include "bindings/core/v8/V8Binding.h" |
| 9 #include "bindings/core/v8/V8BindingMacros.h" | 9 #include "bindings/core/v8/V8BindingMacros.h" |
| 10 #include "bindings/core/v8/V8CustomElementsRegistry.h" | 10 #include "bindings/core/v8/V8CustomElementRegistry.h" |
| 11 #include "bindings/core/v8/V8Element.h" | 11 #include "bindings/core/v8/V8Element.h" |
| 12 #include "bindings/core/v8/V8ErrorHandler.h" | 12 #include "bindings/core/v8/V8ErrorHandler.h" |
| 13 #include "bindings/core/v8/V8HiddenValue.h" | 13 #include "bindings/core/v8/V8HiddenValue.h" |
| 14 #include "bindings/core/v8/V8ScriptRunner.h" | 14 #include "bindings/core/v8/V8ScriptRunner.h" |
| 15 #include "bindings/core/v8/V8ThrowException.h" | 15 #include "bindings/core/v8/V8ThrowException.h" |
| 16 #include "core/dom/ExceptionCode.h" | 16 #include "core/dom/ExceptionCode.h" |
| 17 #include "core/dom/custom/CustomElement.h" | 17 #include "core/dom/custom/CustomElement.h" |
| 18 #include "core/events/ErrorEvent.h" | 18 #include "core/events/ErrorEvent.h" |
| 19 #include "core/html/HTMLElement.h" | 19 #include "core/html/HTMLElement.h" |
| 20 #include "v8.h" | 20 #include "v8.h" |
| 21 #include "wtf/Allocator.h" | 21 #include "wtf/Allocator.h" |
| 22 | 22 |
| 23 namespace blink { | 23 namespace blink { |
| 24 | 24 |
| 25 // Retrieves the custom elements constructor -> name map, creating it | 25 // Retrieves the custom elements constructor -> name map, creating it |
| 26 // if necessary. The same map is used to keep prototypes alive. | 26 // if necessary. The same map is used to keep prototypes alive. |
| 27 static v8::Local<v8::Map> ensureCustomElementsRegistryMap( | 27 static v8::Local<v8::Map> ensureCustomElementRegistryMap( |
| 28 ScriptState* scriptState, | 28 ScriptState* scriptState, |
| 29 CustomElementsRegistry* registry) | 29 CustomElementRegistry* registry) |
| 30 { | 30 { |
| 31 CHECK(scriptState->world().isMainWorld()); | 31 CHECK(scriptState->world().isMainWorld()); |
| 32 v8::Local<v8::String> name = V8HiddenValue::customElementsRegistryMap( | 32 v8::Local<v8::String> name = V8HiddenValue::customElementsRegistryMap( |
| 33 scriptState->isolate()); | 33 scriptState->isolate()); |
| 34 v8::Local<v8::Object> wrapper = | 34 v8::Local<v8::Object> wrapper = |
| 35 toV8(registry, scriptState).As<v8::Object>(); | 35 toV8(registry, scriptState).As<v8::Object>(); |
| 36 v8::Local<v8::Value> map = | 36 v8::Local<v8::Value> map = |
| 37 V8HiddenValue::getHiddenValue(scriptState, wrapper, name); | 37 V8HiddenValue::getHiddenValue(scriptState, wrapper, name); |
| 38 if (map.IsEmpty()) { | 38 if (map.IsEmpty()) { |
| 39 map = v8::Map::New(scriptState->isolate()); | 39 map = v8::Map::New(scriptState->isolate()); |
| 40 V8HiddenValue::setHiddenValue(scriptState, wrapper, name, map); | 40 V8HiddenValue::setHiddenValue(scriptState, wrapper, name, map); |
| 41 } | 41 } |
| 42 return map.As<v8::Map>(); | 42 return map.As<v8::Map>(); |
| 43 } | 43 } |
| 44 | 44 |
| 45 ScriptCustomElementDefinition* ScriptCustomElementDefinition::forConstructor( | 45 ScriptCustomElementDefinition* ScriptCustomElementDefinition::forConstructor( |
| 46 ScriptState* scriptState, | 46 ScriptState* scriptState, |
| 47 CustomElementsRegistry* registry, | 47 CustomElementRegistry* registry, |
| 48 const v8::Local<v8::Value>& constructor) | 48 const v8::Local<v8::Value>& constructor) |
| 49 { | 49 { |
| 50 v8::Local<v8::Map> map = | 50 v8::Local<v8::Map> map = |
| 51 ensureCustomElementsRegistryMap(scriptState, registry); | 51 ensureCustomElementRegistryMap(scriptState, registry); |
| 52 v8::Local<v8::Value> nameValue = map->Get(scriptState->context(), constructo
r).ToLocalChecked(); | 52 v8::Local<v8::Value> nameValue = map->Get(scriptState->context(), constructo
r).ToLocalChecked(); |
| 53 if (!nameValue->IsString()) | 53 if (!nameValue->IsString()) |
| 54 return nullptr; | 54 return nullptr; |
| 55 AtomicString name = toCoreAtomicString(nameValue.As<v8::String>()); | 55 AtomicString name = toCoreAtomicString(nameValue.As<v8::String>()); |
| 56 | 56 |
| 57 // This downcast is safe because only | 57 // This downcast is safe because only |
| 58 // ScriptCustomElementDefinitions have a name associated with a V8 | 58 // ScriptCustomElementDefinitions have a name associated with a V8 |
| 59 // constructor in the map; see | 59 // constructor in the map; see |
| 60 // ScriptCustomElementDefinition::create. This relies on three | 60 // ScriptCustomElementDefinition::create. This relies on three |
| 61 // things: | 61 // things: |
| 62 // | 62 // |
| 63 // 1. Only ScriptCustomElementDefinition adds entries to the map. | 63 // 1. Only ScriptCustomElementDefinition adds entries to the map. |
| 64 // Audit the use of V8HiddenValue/hidden values in general and | 64 // Audit the use of V8HiddenValue/hidden values in general and |
| 65 // how the map is handled--it should never be leaked to script. | 65 // how the map is handled--it should never be leaked to script. |
| 66 // | 66 // |
| 67 // 2. CustomElementsRegistry does not overwrite definitions with a | 67 // 2. CustomElementRegistry does not overwrite definitions with a |
| 68 // given name--see the CHECK in CustomElementsRegistry::define | 68 // given name--see the CHECK in CustomElementRegistry::define |
| 69 // --and adds ScriptCustomElementDefinitions to the map without | 69 // --and adds ScriptCustomElementDefinitions to the map without |
| 70 // fail. | 70 // fail. |
| 71 // | 71 // |
| 72 // 3. The relationship between the CustomElementsRegistry and its | 72 // 3. The relationship between the CustomElementRegistry and its |
| 73 // map is never mixed up; this is guaranteed by the bindings | 73 // map is never mixed up; this is guaranteed by the bindings |
| 74 // system which provides a stable wrapper, and the map hangs | 74 // system which provides a stable wrapper, and the map hangs |
| 75 // off the wrapper. | 75 // off the wrapper. |
| 76 // | 76 // |
| 77 // At a meta-level, this downcast is safe because there is | 77 // At a meta-level, this downcast is safe because there is |
| 78 // currently only one implementation of CustomElementDefinition in | 78 // currently only one implementation of CustomElementDefinition in |
| 79 // product code and that is ScriptCustomElementDefinition. But | 79 // product code and that is ScriptCustomElementDefinition. But |
| 80 // that may change in the future. | 80 // that may change in the future. |
| 81 CustomElementDefinition* definition = registry->definitionForName(name); | 81 CustomElementDefinition* definition = registry->definitionForName(name); |
| 82 CHECK(definition); | 82 CHECK(definition); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 93 return; | 93 return; |
| 94 | 94 |
| 95 array->Set(scriptState->context(), index, value).ToChecked(); | 95 array->Set(scriptState->context(), index, value).ToChecked(); |
| 96 | 96 |
| 97 persistent.set(scriptState->isolate(), value); | 97 persistent.set(scriptState->isolate(), value); |
| 98 persistent.setPhantom(); | 98 persistent.setPhantom(); |
| 99 } | 99 } |
| 100 | 100 |
| 101 ScriptCustomElementDefinition* ScriptCustomElementDefinition::create( | 101 ScriptCustomElementDefinition* ScriptCustomElementDefinition::create( |
| 102 ScriptState* scriptState, | 102 ScriptState* scriptState, |
| 103 CustomElementsRegistry* registry, | 103 CustomElementRegistry* registry, |
| 104 const CustomElementDescriptor& descriptor, | 104 const CustomElementDescriptor& descriptor, |
| 105 const v8::Local<v8::Object>& constructor, | 105 const v8::Local<v8::Object>& constructor, |
| 106 const v8::Local<v8::Object>& prototype, | 106 const v8::Local<v8::Object>& prototype, |
| 107 const v8::Local<v8::Function>& connectedCallback, | 107 const v8::Local<v8::Function>& connectedCallback, |
| 108 const v8::Local<v8::Function>& disconnectedCallback, | 108 const v8::Local<v8::Function>& disconnectedCallback, |
| 109 const v8::Local<v8::Function>& adoptedCallback, | 109 const v8::Local<v8::Function>& adoptedCallback, |
| 110 const v8::Local<v8::Function>& attributeChangedCallback, | 110 const v8::Local<v8::Function>& attributeChangedCallback, |
| 111 const HashSet<AtomicString>& observedAttributes) | 111 const HashSet<AtomicString>& observedAttributes) |
| 112 { | 112 { |
| 113 ScriptCustomElementDefinition* definition = | 113 ScriptCustomElementDefinition* definition = |
| 114 new ScriptCustomElementDefinition( | 114 new ScriptCustomElementDefinition( |
| 115 scriptState, | 115 scriptState, |
| 116 descriptor, | 116 descriptor, |
| 117 constructor, | 117 constructor, |
| 118 prototype, | 118 prototype, |
| 119 connectedCallback, | 119 connectedCallback, |
| 120 disconnectedCallback, | 120 disconnectedCallback, |
| 121 adoptedCallback, | 121 adoptedCallback, |
| 122 attributeChangedCallback, | 122 attributeChangedCallback, |
| 123 observedAttributes); | 123 observedAttributes); |
| 124 | 124 |
| 125 // Add a constructor -> name mapping to the registry. | 125 // Add a constructor -> name mapping to the registry. |
| 126 v8::Local<v8::Value> nameValue = | 126 v8::Local<v8::Value> nameValue = |
| 127 v8String(scriptState->isolate(), descriptor.name()); | 127 v8String(scriptState->isolate(), descriptor.name()); |
| 128 v8::Local<v8::Map> map = | 128 v8::Local<v8::Map> map = |
| 129 ensureCustomElementsRegistryMap(scriptState, registry); | 129 ensureCustomElementRegistryMap(scriptState, registry); |
| 130 map->Set(scriptState->context(), constructor, nameValue).ToLocalChecked(); | 130 map->Set(scriptState->context(), constructor, nameValue).ToLocalChecked(); |
| 131 definition->m_constructor.setPhantom(); | 131 definition->m_constructor.setPhantom(); |
| 132 | 132 |
| 133 // We add the prototype and callbacks here to keep them alive. We use the | 133 // We add the prototype and callbacks here to keep them alive. We use the |
| 134 // name as the key because it is unique per-registry. | 134 // name as the key because it is unique per-registry. |
| 135 v8::Local<v8::Array> array = v8::Array::New(scriptState->isolate(), 5); | 135 v8::Local<v8::Array> array = v8::Array::New(scriptState->isolate(), 5); |
| 136 keepAlive(array, 0, prototype, definition->m_prototype, scriptState); | 136 keepAlive(array, 0, prototype, definition->m_prototype, scriptState); |
| 137 keepAlive(array, 1, connectedCallback, definition->m_connectedCallback, scri
ptState); | 137 keepAlive(array, 1, connectedCallback, definition->m_connectedCallback, scri
ptState); |
| 138 keepAlive(array, 2, disconnectedCallback, definition->m_disconnectedCallback
, scriptState); | 138 keepAlive(array, 2, disconnectedCallback, definition->m_disconnectedCallback
, scriptState); |
| 139 keepAlive(array, 3, adoptedCallback, definition->m_adoptedCallback, scriptSt
ate); | 139 keepAlive(array, 3, adoptedCallback, definition->m_adoptedCallback, scriptSt
ate); |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 371 v8String(isolate, name.localName()), | 371 v8String(isolate, name.localName()), |
| 372 v8StringOrNull(isolate, oldValue), | 372 v8StringOrNull(isolate, oldValue), |
| 373 v8StringOrNull(isolate, newValue), | 373 v8StringOrNull(isolate, newValue), |
| 374 v8String(isolate, name.namespaceURI()), | 374 v8String(isolate, name.namespaceURI()), |
| 375 }; | 375 }; |
| 376 runCallback(m_attributeChangedCallback.newLocal(isolate), element, | 376 runCallback(m_attributeChangedCallback.newLocal(isolate), element, |
| 377 argc, argv); | 377 argc, argv); |
| 378 } | 378 } |
| 379 | 379 |
| 380 } // namespace blink | 380 } // namespace blink |
| OLD | NEW |