Changeset 205261 in webkit
- Timestamp:
- Aug 31, 2016 12:31:11 PM (8 years ago)
- Location:
- trunk
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r205258 r205261 1 2016-08-31 Ryosuke Niwa <rniwa@webkit.org> 2 3 Add the check for reentrancy to CustomElementRegistry 4 https://bugs.webkit.org/show_bug.cgi?id=161423 5 6 Reviewed by Antti Koivisto. 7 8 Add test cases for reentrancy during customElements.define. 9 10 * fast/custom-elements/CustomElementRegistry-expected.txt: 11 * fast/custom-elements/CustomElementRegistry.html: 12 1 13 2016-08-31 Chris Dumez <cdumez@apple.com> 2 14 -
trunk/LayoutTests/fast/custom-elements/CustomElementRegistry-expected.txt
r205220 r205261 1 1 2 2 PASS CustomElementRegistry interface must have define as a method 3 PASS customElements.define must throw when the element interface is not a constructor 3 4 PASS customElements.define must throw with an invalid name 4 5 PASS customElements.define must throw when there is already a custom element of the same name 5 PASS customElements.define must throw when there is already a custom element with the same class 6 PASS customElements.define must throw when the element interface is not a constructor 6 PASS customElements.define must throw a NotSupportedError when there is already a custom element with the same class 7 PASS customElements.define must throw a NotSupportedError when element definition is running flag is set 8 PASS customElements.define must check IsConstructor on the constructor before checking the element definition is running flag 9 PASS customElements.define must validate the custom element name before checking the element definition is running flag 10 PASS customElements.define must not throw when defining another custom element in a different global object during Get(constructor, "prototype") 11 PASS Custom Elements: CustomElementRegistry interface 7 12 PASS customElements.define must get "prototype" property of the constructor 8 13 PASS customElements.define must rethrow an exception thrown while getting "prototype" property of the constructor -
trunk/LayoutTests/fast/custom-elements/CustomElementRegistry.html
r205220 r205261 19 19 20 20 test(function () { 21 assert_throws({'name': 'TypeError'}, function () { customElements.define('badname', 1); }, 22 'customElements.define must throw a TypeError when the element interface is a number'); 23 assert_throws({'name': 'TypeError'}, function () { customElements.define('badname', '123'); }, 24 'customElements.define must throw a TypeError when the element interface is a string'); 25 assert_throws({'name': 'TypeError'}, function () { customElements.define('badname', {}); }, 26 'customElements.define must throw a TypeError when the element interface is an object'); 27 assert_throws({'name': 'TypeError'}, function () { customElements.define('badname', []); }, 28 'customElements.define must throw a TypeError when the element interface is an array'); 29 }, 'customElements.define must throw when the element interface is not a constructor'); 30 31 test(function () { 21 32 class MyCustomElement extends HTMLElement {}; 22 33 … … 50 61 test(function () { 51 62 class SomeCustomElement extends HTMLElement {}; 52 class OtherCustomElement extends HTMLElement {}; 63 64 var calls = []; 65 var OtherCustomElement = new Proxy(class extends HTMLElement {}, { 66 get: function (target, name) { 67 calls.push(name); 68 return target[name]; 69 } 70 }) 53 71 54 72 customElements.define('some-custom-element', SomeCustomElement); 55 73 assert_throws({'name': 'NotSupportedError'}, function () { customElements.define('some-custom-element', OtherCustomElement); }, 56 74 'customElements.define must throw a NotSupportedError if the specified tag name is already used'); 75 assert_array_equals(calls, [], 'customElements.define must validate the custom element name before getting the prototype of the constructor'); 57 76 58 77 }, 'customElements.define must throw when there is already a custom element of the same name'); … … 65 84 'customElements.define must throw a NotSupportedError if the specified class already defines an element'); 66 85 67 }, 'customElements.define must throw when there is already a custom element with the same class'); 68 69 test(function () { 70 assert_throws({'name': 'TypeError'}, function () { customElements.define('invalid-element', 1); }, 71 'customElements.define must throw a TypeError when the element interface is a number'); 72 assert_throws({'name': 'TypeError'}, function () { customElements.define('invalid-element', '123'); }, 73 'customElements.define must throw a TypeError when the element interface is a string'); 74 assert_throws({'name': 'TypeError'}, function () { customElements.define('invalid-element', {}); }, 75 'customElements.define must throw a TypeError when the element interface is an object'); 76 assert_throws({'name': 'TypeError'}, function () { customElements.define('invalid-element', []); }, 77 'customElements.define must throw a TypeError when the element interface is an array'); 78 }, 'customElements.define must throw when the element interface is not a constructor'); 86 }, 'customElements.define must throw a NotSupportedError when there is already a custom element with the same class'); 87 88 test(function () { 89 var outerCalls = []; 90 var OuterCustomElement = new Proxy(class extends HTMLElement { }, { 91 get: function (target, name) { 92 outerCalls.push(name); 93 customElements.define('inner-custom-element', InnerCustomElement); 94 return target[name]; 95 } 96 }); 97 var innerCalls = []; 98 var InnerCustomElement = new Proxy(class extends HTMLElement { }, { 99 get: function (target, name) { 100 outerCalls.push(name); 101 return target[name]; 102 } 103 }); 104 105 assert_throws({'name': 'NotSupportedError'}, function () { customElements.define('outer-custom-element', OuterCustomElement); }, 106 'customElements.define must throw a NotSupportedError if the specified class already defines an element'); 107 assert_array_equals(outerCalls, ['prototype'], 'customElements.define must get "prototype"'); 108 assert_array_equals(innerCalls, [], 109 'customElements.define must throw a NotSupportedError when element definition is running flag is set' 110 + ' before getting the prototype of the constructor'); 111 112 }, 'customElements.define must throw a NotSupportedError when element definition is running flag is set'); 113 114 test(function () { 115 var calls = []; 116 var ElementWithBadInnerConstructor = new Proxy(class extends HTMLElement { }, { 117 get: function (target, name) { 118 calls.push(name); 119 customElements.define('inner-custom-element', 1); 120 return target[name]; 121 } 122 }); 123 124 assert_throws({'name': 'TypeError'}, function () { 125 customElements.define('element-with-bad-inner-constructor', ElementWithBadInnerConstructor); 126 }, 'customElements.define must throw a NotSupportedError if IsConstructor(constructor) is false'); 127 128 assert_array_equals(calls, ['prototype'], 'customElements.define must get "prototype"'); 129 }, 'customElements.define must check IsConstructor on the constructor before checking the element definition is running flag'); 130 131 test(function () { 132 var calls = []; 133 var ElementWithBadInnerName = new Proxy(class extends HTMLElement { }, { 134 get: function (target, name) { 135 calls.push(name); 136 customElements.define('badname', class extends HTMLElement {}); 137 return target[name]; 138 } 139 }); 140 141 assert_throws({'name': 'SyntaxError'}, function () { 142 customElements.define('element-with-bad-inner-name', ElementWithBadInnerName); 143 }, 'customElements.define must throw a SyntaxError if the specified name is not a valid custom element name'); 144 145 assert_array_equals(calls, ['prototype'], 'customElements.define must get "prototype"'); 146 }, 'customElements.define must validate the custom element name before checking the element definition is running flag'); 147 148 (function () { 149 var testCase = async_test('customElements.define must not throw' 150 +' when defining another custom element in a different global object during Get(constructor, "prototype")', {timeout: 100}); 151 152 var iframe = document.createElement('iframe'); 153 iframe.onload = function () { 154 testCase.step(function () { 155 var InnerCustomElement = class extends iframe.contentWindow.HTMLElement {}; 156 var calls = []; 157 var proxy = new Proxy(class extends HTMLElement { }, { 158 get: function (target, name) { 159 calls.push(name); 160 iframe.contentWindow.customElements.define('another-custom-element', InnerCustomElement); 161 return target[name]; 162 } 163 }) 164 customElements.define('element-with-inner-element-define', proxy); 165 assert_array_equals(calls, ['prototype'], 'customElements.define must get "prototype"'); 166 assert_true(iframe.contentDocument.createElement('another-custom-element') instanceof InnerCustomElement); 167 }); 168 document.body.removeChild(iframe); 169 testCase.done(); 170 } 171 172 document.body.appendChild(iframe); 173 })(); 174 175 test(function () { 176 var calls = []; 177 var ElementWithBadInnerName = new Proxy(class extends HTMLElement { }, { 178 get: function (target, name) { 179 calls.push(name); 180 customElements.define('badname', class extends HTMLElement {}); 181 return target[name]; 182 } 183 }); 184 185 assert_throws({'name': 'SyntaxError'}, function () { 186 customElements.define('element-with-bad-inner-name', ElementWithBadInnerName); 187 }, 'customElements.define must throw a SyntaxError if the specified name is not a valid custom element name'); 188 189 assert_array_equals(calls, ['prototype'], 'customElements.define must get "prototype"'); 190 }, ''); 79 191 80 192 test(function () { -
trunk/Source/WebCore/ChangeLog
r205257 r205261 1 2016-08-31 Ryosuke Niwa <rniwa@webkit.org> 2 3 Add the check for reentrancy to CustomElementRegistry 4 https://bugs.webkit.org/show_bug.cgi?id=161423 5 6 Reviewed by Antti Koivisto. 7 8 Added the "element definition is running" flag to JSCustomElementRegistry: 9 https://html.spec.whatwg.org/multipage/scripting.html#element-definition-is-running 10 11 And added an exception for when this flag is set during JSCustomElementRegistry::define: 12 https://html.spec.whatwg.org/multipage/scripting.html#dom-customelementregistry-define 13 14 Tests: fast/custom-elements/CustomElementRegistry.html 15 16 * bindings/js/JSCustomElementRegistryCustom.cpp: 17 (WebCore::JSCustomElementRegistry::define): Throw NotSupportedError when m_elementDefinitionIsRunning is true. 18 * dom/CustomElementRegistry.h: 19 (WebCore::CustomElementRegistry::elementDefinitionIsRunning): Added. 20 1 21 2016-08-30 Ryosuke Niwa <rniwa@webkit.org> 2 22 -
trunk/Source/WebCore/bindings/js/JSCustomElementRegistryCustom.cpp
r205198 r205261 93 93 94 94 CustomElementRegistry& registry = wrapped(); 95 96 if (registry.elementDefinitionIsRunning()) { 97 throwNotSupportedError(state, scope, ASCIILiteral("Cannot define a custom element while defining another custom element")); 98 return jsUndefined(); 99 } 100 TemporaryChange<bool> change(registry.elementDefinitionIsRunning(), true); 101 95 102 if (registry.findInterface(localName)) { 96 103 throwNotSupportedError(state, scope, ASCIILiteral("Cannot define multiple custom elements with the same tag name")); -
trunk/Source/WebCore/dom/CustomElementRegistry.h
r205220 r205261 30 30 #include "QualifiedName.h" 31 31 #include <wtf/HashMap.h> 32 #include <wtf/TemporaryChange.h> 32 33 #include <wtf/text/AtomicString.h> 33 34 #include <wtf/text/AtomicStringHash.h> … … 42 43 namespace WebCore { 43 44 45 class CustomElementRegistry; 44 46 class Element; 45 47 class JSCustomElementInterface; … … 53 55 void addElementDefinition(Ref<JSCustomElementInterface>&&); 54 56 void addUpgradeCandidate(Element&); 57 58 bool& elementDefinitionIsRunning() { return m_elementDefinitionIsRunning; } 55 59 56 60 JSCustomElementInterface* findInterface(const QualifiedName&) const; … … 67 71 HashMap<AtomicString, Ref<JSCustomElementInterface>> m_nameMap; 68 72 HashMap<const JSC::JSObject*, JSCustomElementInterface*> m_constructorMap; 73 74 bool m_elementDefinitionIsRunning { false }; 75 76 friend class ElementDefinitionIsRunningTemporaryChange; 69 77 }; 70 78
Note: See TracChangeset
for help on using the changeset viewer.