Changeset 195087 in webkit
- Timestamp:
- Jan 14, 2016, 6:59:03 PM (9 years ago)
- Location:
- trunk
- Files:
-
- 9 added
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r195078 r195087 1 2016-01-14 Ryosuke Niwa <rniwa@webkit.org> 2 3 Add document.defineCustomElement 4 https://bugs.webkit.org/show_bug.cgi?id=153092 5 6 Reviewed by Chris Dumez. 7 8 Added tests for document.defineCustomElement and instantiating custom elements. 9 10 * TestExpectations: Skipped the tests on non-Mac ports. 11 * fast/custom-elements: Added. 12 * fast/custom-elements/Document-defineCustomElement-expected.txt: Added. 13 * fast/custom-elements/Document-defineCustomElement.html: Added. 14 * fast/custom-elements/HTMLElement-constructor-expected.txt: Added. 15 * fast/custom-elements/HTMLElement-constructor.html: Added. 16 * platform/mac/TestExpectations: 17 1 18 2016-01-14 Beth Dakin <bdakin@apple.com> 2 19 -
trunk/LayoutTests/TestExpectations
r195010 r195087 741 741 webkit.org/b/148925 svg/dom/svg-root-lengths.html [ Pass Failure ] 742 742 743 webkit.org/b/150225 fast/custom-elements [ Failure ] 743 744 webkit.org/b/148695 fast/shadow-dom [ Failure ImageOnlyFailure ] 744 745 -
trunk/LayoutTests/platform/mac/TestExpectations
r195003 r195087 1259 1259 webkit.org/b/149441 fast/shadow-dom/css-scoping-shadow-slot-display-override.html [ ImageOnlyFailure ] 1260 1260 1261 webkit.org/b/150225 fast/custom-elements [ Pass ] 1262 1261 1263 # Times out in debug. 1262 1264 [ Debug ] js/regress/getter-richards-try-catch.html [ Skip ] -
trunk/Source/WebCore/CMakeLists.txt
r194967 r195087 1115 1115 bindings/js/JSCryptoKeySerializationJWK.cpp 1116 1116 bindings/js/JSCryptoOperationData.cpp 1117 bindings/js/JSCustomElementInterface.cpp 1117 1118 bindings/js/JSCustomEventCustom.cpp 1118 1119 bindings/js/JSCustomSQLStatementErrorCallback.cpp … … 1408 1409 dom/ContainerNodeAlgorithms.cpp 1409 1410 dom/ContextDestructionObserver.cpp 1411 dom/CustomElementDefinitions.cpp 1410 1412 dom/CustomEvent.cpp 1411 1413 dom/DOMCoreException.cpp -
trunk/Source/WebCore/ChangeLog
r195082 r195087 1 2016-01-14 Ryosuke Niwa <rniwa@webkit.org> 2 3 Add document.defineCustomElement 4 https://bugs.webkit.org/show_bug.cgi?id=153092 5 6 Reviewed by Chris Dumez. 7 8 Added document.defineCustomElement and added a constructor to HTMLElement which can be called 9 as "super" in a subclass of HTMLElement. This is a prototype of new custom elements API and 10 willfully violates the current specification at http://w3c.github.io/webcomponents/spec/custom/ 11 12 Each author defined class can define multiple elements using distinct tag names. In such cases, 13 the super call must specify the tag name. e.g. 14 15 class SomeCustomElement extends HTMLElement { constructor(name) { super(name); } } 16 document.defineCustomElement('some-custom-element', SomeCustomElement); 17 document.defineCustomElement('other-custom-element', SomeCustomElement); 18 new SomeCustomElement('some-custom-element'); 19 20 When a class is associated with exactly one tag name, the argument can be omitted. e.g. 21 22 class AnotherCustomElement extends HTMLElement {} 23 document.defineCustomElement('another-custom-element', AnotherCustomElement); 24 new AnotherCustomElement(); 25 26 We allow only subclassing of HTMLElement and only in (X)HTML namespace. 27 28 Tests: fast/custom-elements/Document-defineCustomElement.html 29 fast/custom-elements/HTMLElement-constructor.html 30 31 * CMakeLists.txt: 32 * WebCore.xcodeproj/project.pbxproj: 33 34 * bindings/js/JSCustomElementInterface.cpp: Added. Abstracts an author-defined class associated 35 with a custom element. It's a Active DOM object and lives until the associated document dies. 36 (WebCore::JSCustomElementInterface::JSCustomElementInterface): 37 (WebCore::JSCustomElementInterface::~JSCustomElementInterface): 38 * bindings/js/JSCustomElementInterface.h: Added. 39 (WebCore::JSCustomElementInterface::create): 40 (WebCore::JSCustomElementInterface::scriptExecutionContext): 41 (WebCore::JSCustomElementInterface::constructor): 42 43 * bindings/js/JSDocumentCustom.cpp: 44 (WebCore::JSDocument::defineCustomElement): Added. Define a custom element by associating a tag 45 name with an author defined JS class after validating arguments. 46 47 * bindings/js/JSHTMLElementCustom.cpp: 48 (WebCore::constructJSHTMLElement): Added. Look up the tag name based on new.target if one is not 49 specified. If a tag name is specified, check that new.target is associated with the tag name. 50 51 * dom/CustomElementDefinitions.cpp: Added. 52 (WebCore::CustomElementDefinitions::checkName): Added. Restricts tag names similarly to 53 http://w3c.github.io/webcomponents/spec/custom/#dfn-custom-element-type 54 (WebCore::CustomElementDefinitions::defineElement): Added. Associates a JS class with a tag name. 55 (WebCore::CustomElementDefinitions::findInterface): Added. Finds a JS class by a tag name. 56 (WebCore::CustomElementDefinitions::findName): Added. Finds a tag name by a JS class. 57 * dom/CustomElementDefinitions.h: Added. 58 (WebCore::CustomElementDefinitions::CustomElementInfo): Added. 59 60 * dom/Document.cpp: 61 (WebCore::Document::ensureCustomElementDefinitions): Added. 62 * dom/Document.h: 63 (WebCore::Document::customElementDefinitions): Added. 64 65 * dom/Document.idl: 66 * html/HTMLElement.idl: 67 1 68 2016-01-14 Simon Fraser <simon.fraser@apple.com> 2 69 -
trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj
r195005 r195087 3999 3999 9BD0BF9312A42BF50072FD43 /* ScopedEventQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 9BD0BF9112A42BF50072FD43 /* ScopedEventQueue.h */; }; 4000 4000 9BD0BF9412A42BF50072FD43 /* ScopedEventQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9BD0BF9212A42BF50072FD43 /* ScopedEventQueue.cpp */; }; 4001 9BD4E9161C462872005065BC /* JSCustomElementInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9BD4E9141C462872005065BC /* JSCustomElementInterface.cpp */; }; 4002 9BD4E9171C462872005065BC /* JSCustomElementInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = 9BD4E9151C462872005065BC /* JSCustomElementInterface.h */; }; 4003 9BD4E91A1C462CFC005065BC /* CustomElementDefinitions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9BD4E9181C462CFC005065BC /* CustomElementDefinitions.cpp */; }; 4004 9BD4E91B1C462CFC005065BC /* CustomElementDefinitions.h in Headers */ = {isa = PBXBuildFile; fileRef = 9BD4E9191C462CFC005065BC /* CustomElementDefinitions.h */; }; 4001 4005 9BD8A95A18BEFC7600987E9A /* CollectionIndexCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9BD8A95918BEFC7600987E9A /* CollectionIndexCache.cpp */; }; 4002 4006 9BDA64D71B975CE5009C4387 /* JSShadowRoot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B6BC9601B975966005AE1F0 /* JSShadowRoot.cpp */; }; … … 11573 11577 9BD0BF9112A42BF50072FD43 /* ScopedEventQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScopedEventQueue.h; sourceTree = "<group>"; }; 11574 11578 9BD0BF9212A42BF50072FD43 /* ScopedEventQueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScopedEventQueue.cpp; sourceTree = "<group>"; }; 11579 9BD4E9141C462872005065BC /* JSCustomElementInterface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCustomElementInterface.cpp; sourceTree = "<group>"; }; 11580 9BD4E9151C462872005065BC /* JSCustomElementInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCustomElementInterface.h; sourceTree = "<group>"; }; 11581 9BD4E9181C462CFC005065BC /* CustomElementDefinitions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CustomElementDefinitions.cpp; sourceTree = "<group>"; }; 11582 9BD4E9191C462CFC005065BC /* CustomElementDefinitions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CustomElementDefinitions.h; sourceTree = "<group>"; }; 11575 11583 9BD8A95918BEFC7600987E9A /* CollectionIndexCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CollectionIndexCache.cpp; sourceTree = "<group>"; }; 11576 11584 9BF9A87E1648DD2F001C6B23 /* JSHTMLFormControlsCollection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSHTMLFormControlsCollection.cpp; sourceTree = "<group>"; }; … … 21957 21965 C585A66011D4FAC5004C3E4B /* IDBBindingUtilities.cpp */, 21958 21966 C585A66111D4FAC5004C3E4B /* IDBBindingUtilities.h */, 21967 9BD4E9141C462872005065BC /* JSCustomElementInterface.cpp */, 21968 9BD4E9151C462872005065BC /* JSCustomElementInterface.h */, 21959 21969 E157A8EE18185425009F821D /* JSCryptoAlgorithmBuilder.cpp */, 21960 21970 E157A8EF18185425009F821D /* JSCryptoAlgorithmBuilder.h */, … … 23831 23841 97627B8B14FB3CEE002CDCA1 /* ContextDestructionObserver.cpp */, 23832 23842 97627B8C14FB3CEE002CDCA1 /* ContextDestructionObserver.h */, 23843 9BD4E9181C462CFC005065BC /* CustomElementDefinitions.cpp */, 23844 9BD4E9191C462CFC005065BC /* CustomElementDefinitions.h */, 23833 23845 62CD32561157E57C0063B0A7 /* CustomEvent.cpp */, 23834 23846 62CD32571157E57C0063B0A7 /* CustomEvent.h */, … … 25252 25264 85E7119C0AC5D5350053270F /* DOMHTMLAreaElementInternal.h in Headers */, 25253 25265 859A9C470AA5E3BD00B694B2 /* DOMHTMLBaseElement.h in Headers */, 25266 9BD4E9171C462872005065BC /* JSCustomElementInterface.h in Headers */, 25254 25267 85E7119D0AC5D5350053270F /* DOMHTMLBaseElementInternal.h in Headers */, 25255 25268 85ECBEED0AA7626900544F0B /* DOMHTMLBaseFontElement.h in Headers */, … … 26427 26440 B2FA3D710AB75A6F000E5AC4 /* JSSVGFECompositeElement.h in Headers */, 26428 26441 19BFF64F11C0F2AC00B8C04D /* JSSVGFEConvolveMatrixElement.h in Headers */, 26442 9BD4E91B1C462CFC005065BC /* CustomElementDefinitions.h in Headers */, 26429 26443 B2FA3D730AB75A6F000E5AC4 /* JSSVGFEDiffuseLightingElement.h in Headers */, 26430 26444 B2FA3D750AB75A6F000E5AC4 /* JSSVGFEDisplacementMapElement.h in Headers */, … … 30077 30091 B59DD6A611902A62007E9684 /* JSSQLStatementCallback.cpp in Sources */, 30078 30092 B59DD6AA11902A71007E9684 /* JSSQLStatementErrorCallback.cpp in Sources */, 30093 9BD4E9161C462872005065BC /* JSCustomElementInterface.cpp in Sources */, 30079 30094 514C76380CE9225E007EF3CD /* JSSQLTransaction.cpp in Sources */, 30080 30095 B59DD69E11902A42007E9684 /* JSSQLTransactionCallback.cpp in Sources */, … … 30808 30823 A8DF4AF00980C42C0052981B /* RenderTableRow.cpp in Sources */, 30809 30824 A8DF4AED0980C42C0052981B /* RenderTableSection.cpp in Sources */, 30825 9BD4E91A1C462CFC005065BC /* CustomElementDefinitions.cpp in Sources */, 30810 30826 BCEA488B097D93020094C9E4 /* RenderText.cpp in Sources */, 30811 30827 AB67D1A8097F3AE300F9392E /* RenderTextControl.cpp in Sources */, -
trunk/Source/WebCore/bindings/js/JSDocumentCustom.cpp
r191887 r195087 21 21 #include "JSDocument.h" 22 22 23 #include "CustomElementDefinitions.h" 23 24 #include "ExceptionCode.h" 24 25 #include "Frame.h" … … 131 132 #endif 132 133 134 #if ENABLE(CUSTOM_ELEMENTS) 135 JSValue JSDocument::defineCustomElement(ExecState& state) 136 { 137 AtomicString tagName(state.argument(0).toString(&state)->toAtomicString(&state)); 138 if (UNLIKELY(state.hadException())) 139 return jsUndefined(); 140 141 JSObject* object = state.argument(1).getObject(); 142 ConstructData callData; 143 if (!object || object->methodTable()->getConstructData(object, callData) == ConstructTypeNone) 144 return throwTypeError(&state, "The second argument must be a constructor"); 145 146 Document& document = wrapped(); 147 switch (CustomElementDefinitions::checkName(tagName)) { 148 case CustomElementDefinitions::NameStatus::Valid: 149 break; 150 case CustomElementDefinitions::NameStatus::ConflictsWithBuiltinNames: 151 return throwSyntaxError(&state, "Custom element name cannot be same as one of the builtin elements"); 152 case CustomElementDefinitions::NameStatus::NoHyphen: 153 return throwSyntaxError(&state, "Custom element name must contain a hyphen"); 154 case CustomElementDefinitions::NameStatus::ContainsUpperCase: 155 return throwSyntaxError(&state, "Custom element name cannot contain an upper case letter"); 156 } 157 158 QualifiedName name(nullAtom, tagName, HTMLNames::xhtmlNamespaceURI); 159 auto& definitions = document.ensureCustomElementDefinitions(); 160 if (definitions.findInterface(tagName)) { 161 ExceptionCodeWithMessage ec; 162 ec.code = NOT_SUPPORTED_ERR; 163 ec.message = "Cannot define multiple custom elements with the same tag name"; 164 setDOMException(&state, ec); 165 return jsUndefined(); 166 } 167 definitions.defineElement(name, JSCustomElementInterface::create(object, globalObject())); 168 PrivateName uniquePrivateName; 169 globalObject()->putDirect(globalObject()->vm(), uniquePrivateName, object); 170 171 return jsUndefined(); 172 } 173 #endif 174 133 175 } // namespace WebCore -
trunk/Source/WebCore/bindings/js/JSHTMLElementCustom.cpp
r191887 r195087 27 27 #include "JSHTMLElement.h" 28 28 29 #include "CustomElementDefinitions.h" 29 30 #include "Document.h" 30 31 #include "HTMLFormElement.h" 32 #include <runtime/InternalFunction.h> 31 33 #include <runtime/JSWithScope.h> 32 34 … … 34 36 35 37 using namespace JSC; 38 39 #if ENABLE(CUSTOM_ELEMENTS) 40 EncodedJSValue JSC_HOST_CALL constructJSHTMLElement(ExecState* state) 41 { 42 auto* jsConstructor = jsCast<DOMConstructorObject*>(state->callee()); 43 44 auto* context = jsConstructor->scriptExecutionContext(); 45 if (!is<Document>(context)) 46 return throwConstructorDocumentUnavailableError(*state, "HTMLElement"); 47 auto& document = downcast<Document>(*context); 48 49 auto* definitions = document.customElementDefinitions(); 50 if (!definitions) 51 return throwVMTypeError(state, "new.target is not a valid custom element constructor"); 52 53 VM& vm = state->vm(); 54 JSValue newTargetValue = state->thisValue(); 55 JSObject* newTarget = newTargetValue.getObject(); 56 QualifiedName fullName = definitions->findName(newTarget); 57 if (fullName == nullQName()) { 58 if (UNLIKELY(state->argumentCount() < 1)) 59 return throwVMError(state, createNotEnoughArgumentsError(state)); 60 } 61 62 if (state->argumentCount()) { 63 String name; 64 if (!state->argument(0).getString(state, name)) 65 return throwVMTypeError(state, "The first argument is not a valid custom element name"); 66 67 auto* interface = definitions->findInterface(name); 68 if (!interface) 69 return throwVMTypeError(state, "The first argument is not a valid custom element name"); 70 71 if (newTarget != interface->constructor()) 72 return throwVMTypeError(state, "Attempt to construct a custom element with a wrong interface"); 73 74 fullName = QualifiedName(nullAtom, name, HTMLNames::xhtmlNamespaceURI); 75 } 76 77 auto* globalObject = jsConstructor->globalObject(); 78 Structure* baseStructure = getDOMStructure<JSHTMLElement>(vm, *globalObject); 79 auto* newElementStructure = InternalFunction::createSubclassStructure(state, newTargetValue, baseStructure); 80 if (UNLIKELY(state->hadException())) 81 return JSValue::encode(jsUndefined()); 82 83 Ref<HTMLElement> element = HTMLElement::create(fullName, document); 84 auto* jsElement = JSHTMLElement::create(newElementStructure, globalObject, element.get()); 85 cacheWrapper(globalObject->world(), element.ptr(), jsElement); 86 return JSValue::encode(jsElement); 87 } 88 #endif 36 89 37 90 JSScope* JSHTMLElement::pushEventHandlerScope(ExecState* exec, JSScope* scope) const -
trunk/Source/WebCore/dom/Document.cpp
r194819 r195087 45 45 #include "ContentSecurityPolicy.h" 46 46 #include "CookieJar.h" 47 #include "CustomElementDefinitions.h" 47 48 #include "CustomEvent.h" 48 49 #include "DOMImplementation.h" … … 6353 6354 } 6354 6355 6356 #if ENABLE(CUSTOM_ELEMENTS) 6357 CustomElementDefinitions& Document::ensureCustomElementDefinitions() 6358 { 6359 if (!m_customElementDefinitions) 6360 m_customElementDefinitions = std::make_unique<CustomElementDefinitions>(); 6361 return *m_customElementDefinitions; 6362 } 6363 #endif 6364 6355 6365 LayoutRect Document::absoluteEventHandlerBounds(bool& includesFixedPositionElements) 6356 6366 { -
trunk/Source/WebCore/dom/Document.h
r194584 r195087 176 176 #endif 177 177 178 #if ENABLE(CUSTOM_ELEMENTS) 179 class CustomElementDefinitions; 180 #endif 181 178 182 #if ENABLE(DASHBOARD_SUPPORT) 179 183 struct AnnotatedRegionValue; … … 1215 1219 } 1216 1220 1221 #if ENABLE(CUSTOM_ELEMENTS) 1222 CustomElementDefinitions* customElementDefinitions() { return m_customElementDefinitions.get(); } 1223 CustomElementDefinitions& ensureCustomElementDefinitions(); 1224 #endif 1225 1217 1226 const EventTargetSet* wheelEventTargets() const { return m_wheelEventTargets.get(); } 1218 1227 … … 1748 1757 #endif 1749 1758 1759 #if ENABLE(CUSTOM_ELEMENTS) 1760 std::unique_ptr<CustomElementDefinitions> m_customElementDefinitions; 1761 #endif 1762 1750 1763 RefPtr<CSSFontSelector> m_fontSelector; 1751 1764 -
trunk/Source/WebCore/dom/Document.idl
r190199 r195087 282 282 #endif 283 283 284 #if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT 285 [Custom, RaisesException, Conditional=CUSTOM_ELEMENTS] 286 void defineCustomElement(DOMString tagName, CustomElementInterface elementInterface); 287 #endif 288 284 289 // Page visibility API. 285 290 readonly attribute DOMString visibilityState; -
trunk/Source/WebCore/html/HTMLElement.idl
r190030 r195087 20 20 21 21 [ 22 #if defined(ENABLE_CUSTOM_ELEMENTS) && ENABLE_CUSTOM_ELEMENTS 23 CustomConstructor(optional DOMString localName), 24 #endif 22 25 JSGenerateToNativeObject, 23 26 JSCustomPushEventHandlerScope,
Note:
See TracChangeset
for help on using the changeset viewer.