| Index: Source/bindings/v8/CustomElementHelpers.cpp
|
| diff --git a/Source/bindings/v8/CustomElementHelpers.cpp b/Source/bindings/v8/CustomElementHelpers.cpp
|
| index 2a6087d73491f88c53eabdcc4d2fb9c44e62b0c3..9d4b40d158f0aa79157cd9d42720637419876092 100644
|
| --- a/Source/bindings/v8/CustomElementHelpers.cpp
|
| +++ b/Source/bindings/v8/CustomElementHelpers.cpp
|
| @@ -34,15 +34,19 @@
|
|
|
| #include "HTMLNames.h"
|
| #include "SVGNames.h"
|
| -#include "V8CustomElementConstructor.h"
|
| +#include "V8Document.h"
|
| #include "V8HTMLElementWrapperFactory.h"
|
| #include "V8SVGElementWrapperFactory.h"
|
| #include "bindings/v8/DOMDataStore.h"
|
| #include "bindings/v8/DOMWrapperWorld.h"
|
| #include "bindings/v8/ScriptController.h"
|
| +#include "bindings/v8/ScriptState.h"
|
| #include "bindings/v8/UnsafePersistent.h"
|
| +#include "bindings/v8/V8HiddenPropertyName.h"
|
| #include "bindings/v8/V8PerContextData.h"
|
| #include "core/dom/CustomElementRegistry.h"
|
| +#include "core/dom/Element.h"
|
| +#include "core/dom/ExceptionCode.h"
|
| #include "core/dom/Node.h"
|
| #include "core/html/HTMLElement.h"
|
| #include "core/html/HTMLUnknownElement.h"
|
| @@ -138,27 +142,79 @@ v8::Handle<v8::Object> CustomElementHelpers::createUpgradeCandidateWrapper(PassR
|
| }
|
| }
|
|
|
| -bool CustomElementHelpers::initializeConstructorWrapper(CustomElementConstructor* constructor, const ScriptValue& prototype, ScriptState* state)
|
| +static void constructCustomElement(const v8::FunctionCallbackInfo<v8::Value>& args)
|
| {
|
| - ASSERT(isFeatureAllowed(state));
|
| - ASSERT(!prototype.v8Value().IsEmpty() && prototype.v8Value()->IsObject());
|
| - v8::Handle<v8::Value> wrapperValue = toV8(constructor, state->context()->Global(), state->context()->GetIsolate());
|
| - if (wrapperValue.IsEmpty() || !wrapperValue->IsObject())
|
| - return false;
|
| - v8::Handle<v8::Function> wrapper = v8::Handle<v8::Function>::Cast(wrapperValue);
|
| - // - Object::ForceSet() nor Object::SetAccessor Doesn't work against the "prototype" property of function objects.
|
| - // - Set()-ing here is safe because
|
| - // - Hooking Object.prototype's defineProperty() with "prototype" or "constructor" also doesn't affect on these properties of function objects and
|
| - // - Using Set() is okay becaues each function has "prototype" property from start and Objects.prototype cannot intercept the property access.
|
| - v8::Handle<v8::String> prototypeKey = v8String("prototype", state->context()->GetIsolate());
|
| - ASSERT(wrapper->HasOwnProperty(prototypeKey));
|
| - wrapper->Set(prototypeKey, prototype.v8Value(), v8::ReadOnly);
|
| -
|
| - v8::Handle<v8::String> constructorKey = v8String("constructor", state->context()->GetIsolate());
|
| - v8::Handle<v8::Object> prototypeObject = v8::Handle<v8::Object>::Cast(prototype.v8Value());
|
| - ASSERT(!prototypeObject->HasOwnProperty(constructorKey));
|
| - prototypeObject->ForceSet(constructorKey, wrapper, v8::ReadOnly);
|
| - return true;
|
| + v8::Isolate* isolate = args.GetIsolate();
|
| +
|
| + if (!args.IsConstructCall()) {
|
| + throwTypeError("DOM object constructor cannot be called as a function.", isolate);
|
| + return;
|
| + }
|
| +
|
| + if (args.Length() > 0) {
|
| + throwTypeError(0, isolate);
|
| + return;
|
| + }
|
| +
|
| + Document* document = V8Document::toNative(v8::Handle<v8::Object>::Cast(args.Callee()->GetHiddenValue(V8HiddenPropertyName::document())));
|
| + V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, namespaceURI, args.Callee()->GetHiddenValue(V8HiddenPropertyName::namespaceURI()));
|
| + V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, name, args.Callee()->GetHiddenValue(V8HiddenPropertyName::name()));
|
| + v8::Handle<v8::Value> maybeType = args.Callee()->GetHiddenValue(V8HiddenPropertyName::type());
|
| + V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, type, maybeType);
|
| +
|
| + ExceptionCode ec = 0;
|
| + CustomElementRegistry::CallbackDeliveryScope deliveryScope;
|
| + RefPtr<Element> element = document->createElementNS(namespaceURI, name, maybeType->IsNull() ? nullAtom : type, ec);
|
| + if (ec) {
|
| + setDOMException(ec, isolate);
|
| + return;
|
| + }
|
| + v8SetReturnValue(args, toV8Fast(element.release(), args, document));
|
| +}
|
| +
|
| +ScriptValue CustomElementHelpers::createConstructor(ScriptState* state, const ScriptValue& prototypeValue, Document* document, const AtomicString& namespaceURI, const AtomicString& name, const AtomicString& type)
|
| +{
|
| + v8::Isolate* isolate = state->isolate();
|
| +
|
| + v8::HandleScope handleScope;
|
| + v8::TryCatch tryCatch;
|
| + v8::Local<v8::FunctionTemplate> constructorTemplate = v8::FunctionTemplate::New();
|
| + constructorTemplate->SetCallHandler(constructCustomElement);
|
| + v8::Handle<v8::Function> constructor = constructorTemplate->GetFunction();
|
| + if (tryCatch.HasCaught()) {
|
| + state->setException(tryCatch.Exception());
|
| + return ScriptValue();
|
| + }
|
| + if (constructor.IsEmpty()) {
|
| + state->setException(v8::Local<v8::Value>::New(setDOMException(INVALID_STATE_ERR, isolate)));
|
| + return ScriptValue();
|
| + }
|
| +
|
| + v8::Handle<v8::String> v8Name = v8String(name, isolate);
|
| + v8::Handle<v8::Value> v8Type = v8StringOrNull(type, isolate);
|
| +
|
| + constructor->SetName(v8Type->IsNull() ? v8Name : v8::Handle<v8::String>::Cast(v8Type));
|
| +
|
| + V8HiddenPropertyName::setNamedHiddenReference(constructor, "document", toV8(document, state->context()->Global(), isolate));
|
| + V8HiddenPropertyName::setNamedHiddenReference(constructor, "namespaceURI", v8String(namespaceURI, isolate));
|
| + V8HiddenPropertyName::setNamedHiddenReference(constructor, "name", v8Name);
|
| + V8HiddenPropertyName::setNamedHiddenReference(constructor, "type", v8Type);
|
| +
|
| + // Neither Object::ForceSet nor Object::SetAccessor can set the
|
| + // "prototype" property of function objects, so we use Set()
|
| + // instead. This is safe because each function has "prototype"
|
| + // property from birth so the Function, etc. prototypes will not
|
| + // intercept the property access.
|
| + v8::Handle<v8::Object> prototype = v8::Handle<v8::Object>::Cast(prototypeValue.v8Value());
|
| + v8::Handle<v8::String> prototypeKey = v8String("prototype", isolate);
|
| + ASSERT(constructor->HasOwnProperty(prototypeKey));
|
| + constructor->Set(prototypeKey, prototype, v8::ReadOnly);
|
| +
|
| + prototype->ForceSet(v8String("constructor", isolate), constructor, v8::ReadOnly);
|
| +
|
| + ASSERT(!tryCatch.HasCaught());
|
| +
|
| + return ScriptValue(constructor);
|
| }
|
|
|
| static bool hasValidPrototypeChainFor(v8::Handle<v8::Object> prototypeObject, WrapperTypeInfo* typeInfo, v8::Handle<v8::Context> context)
|
|
|