Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(104)

Unified Diff: third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinition.cpp

Issue 2003033004: Split custom element script use and move it into bindings (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address feedback. Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinition.cpp
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinition.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinition.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d0d3bd051180dce7ef6a8ad89f2a005361ff7fe8
--- /dev/null
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinition.cpp
@@ -0,0 +1,136 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "bindings/core/v8/ScriptCustomElementDefinition.h"
+
+#include "bindings/core/v8/ScriptState.h"
+#include "bindings/core/v8/V8Binding.h"
+#include "bindings/core/v8/V8CustomElementsRegistry.h"
+#include "bindings/core/v8/V8HiddenValue.h"
+#include "wtf/Allocator.h"
+
+namespace blink {
+
+// Retrieves the custom elements constructor -> name map, creating it
+// if necessary. The same map is used to keep prototypes alive.
+static v8::Local<v8::Map> ensureCustomElementsRegistryMap(
+ ScriptState* scriptState,
+ CustomElementsRegistry* registry)
+{
+ CHECK(scriptState->world().isMainWorld());
+ v8::Local<v8::String> name = V8HiddenValue::customElementsRegistryMap(
+ scriptState->isolate());
+ v8::Local<v8::Object> wrapper =
+ toV8(registry, scriptState).As<v8::Object>();
+ v8::Local<v8::Value> map =
+ V8HiddenValue::getHiddenValue(scriptState, wrapper, name);
+ if (map.IsEmpty()) {
+ map = v8::Map::New(scriptState->isolate());
+ V8HiddenValue::setHiddenValue(scriptState, wrapper, name, map);
+ }
+ return map.As<v8::Map>();
+}
+
+ScriptCustomElementDefinition* ScriptCustomElementDefinition::forConstructor(
+ ScriptState* scriptState,
+ CustomElementsRegistry* registry,
+ const v8::Local<v8::Value>& constructor)
+{
+ v8::Local<v8::Map> map =
+ ensureCustomElementsRegistryMap(scriptState, registry);
+ v8::Local<v8::Value> nameValue = v8CallOrCrash(
+ map->Get(scriptState->context(), constructor));
+ if (!nameValue->IsString())
+ return nullptr;
+ AtomicString name = toCoreAtomicString(nameValue.As<v8::String>());
+
+ // This downcast is safe because only
+ // ScriptCustomElementDefinitions have a name associated with a V8
+ // constructor in the map; see
+ // ScriptCustomElementDefinition::create. This relies on three
+ // things:
+ //
+ // 1. Only ScriptCustomElementDefinition adds entries to the map.
+ // Audit the use of V8HiddenValue/hidden values in general and
+ // how the map is handled--it should never be leaked to script.
+ //
+ // 2. CustomElementsRegistry does not overwrite definitions with a
+ // given name--see the CHECK in CustomElementsRegistry::define
+ // --and adds ScriptCustomElementDefinitions to the map without
+ // fail.
+ //
+ // 3. The relationship between the CustomElementsRegistry and its
+ // map is never mixed up; this is guaranteed by the bindings
+ // system which provides a stable wrapper, and the map hangs
+ // off the wrapper.
+ //
+ // At a meta-level, this downcast is safe because there is
+ // currently only one implementation of CustomElementDefinition in
+ // product code and that is ScriptCustomElementDefinition. But
+ // that may change in the future.
+ CustomElementDefinition* definition = registry->definitionForName(name);
+ CHECK(definition);
+ return static_cast<ScriptCustomElementDefinition*>(definition);
+}
+
+ScriptCustomElementDefinition* ScriptCustomElementDefinition::create(
+ ScriptState* scriptState,
+ CustomElementsRegistry* registry,
+ const CustomElementDescriptor& descriptor,
+ const v8::Local<v8::Object>& constructor,
+ const v8::Local<v8::Object>& prototype)
+{
+ ScriptCustomElementDefinition* definition =
+ new ScriptCustomElementDefinition(
+ scriptState,
+ descriptor,
+ constructor,
+ prototype);
+
+ // Add a constructor -> name mapping to the registry.
+ v8::Local<v8::Value> nameValue =
+ v8String(scriptState->isolate(), descriptor.name());
+ v8::Local<v8::Map> map =
+ ensureCustomElementsRegistryMap(scriptState, registry);
+ v8CallOrCrash(map->Set(scriptState->context(), constructor, nameValue));
+ // We add the prototype here to keep it alive; we make it a value
+ // not a key so authors cannot return another constructor as a
+ // prototype to overwrite a constructor in this map. We use the
+ // name because it is unique per-registry.
+ v8CallOrCrash(map->Set(scriptState->context(), nameValue, prototype));
+
+ return definition;
+}
+
+ScriptCustomElementDefinition::ScriptCustomElementDefinition(
+ ScriptState* scriptState,
+ const CustomElementDescriptor& descriptor,
+ const v8::Local<v8::Object>& constructor,
+ const v8::Local<v8::Object>& prototype)
+ : CustomElementDefinition(descriptor)
+ , m_constructor(scriptState->isolate(), constructor)
+ , m_prototype(scriptState->isolate(), prototype)
+{
+ // These objects are kept alive by references from the
+ // CustomElementsRegistry wrapper set up by
+ // ScriptCustomElementDefinition::create.
+ m_constructor.setPhantom();
+ m_prototype.setPhantom();
+}
+
+v8::Local<v8::Object> ScriptCustomElementDefinition::constructor(
+ ScriptState* scriptState) const
+{
+ DCHECK(!m_constructor.isEmpty());
+ return m_constructor.newLocal(scriptState->isolate());
+}
+
+v8::Local<v8::Object> ScriptCustomElementDefinition::prototype(
+ ScriptState* scriptState) const
+{
+ DCHECK(!m_prototype.isEmpty());
+ return m_prototype.newLocal(scriptState->isolate());
+}
+
+} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698