Changeset 197611 in webkit
- Timestamp:
- Mar 4, 2016 11:50:54 PM (8 years ago)
- Location:
- trunk
- Files:
-
- 6 added
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r197610 r197611 1 2016-03-04 Ryosuke Niwa <rniwa@webkit.org> 2 3 Add basic support for attributeChanged lifecycle callback 4 https://bugs.webkit.org/show_bug.cgi?id=155011 5 6 Reviewed by Antti Koivisto. 7 8 Added a test for attributeChangedCallback and a test for the timing of lifecycle callbacks in general. 9 10 * fast/custom-elements/attribute-changed-callback-expected.txt: Added. 11 * fast/custom-elements/attribute-changed-callback.html: Added. 12 * fast/custom-elements/lifecycle-callback-timing-expected.txt: Added. 13 * fast/custom-elements/lifecycle-callback-timing.html: Added. 14 1 15 2016-03-04 Tim Horton <timothy_horton@apple.com> 2 16 -
trunk/Source/WebCore/CMakeLists.txt
r197592 r197611 1454 1454 dom/InlineStyleSheetOwner.cpp 1455 1455 dom/KeyboardEvent.cpp 1456 dom/LifecycleCallbackQueue.cpp 1456 1457 dom/LiveNodeList.cpp 1457 1458 dom/MessageChannel.cpp -
trunk/Source/WebCore/ChangeLog
r197609 r197611 1 2016-03-04 Ryosuke Niwa <rniwa@webkit.org> 2 3 Add basic support for attributeChanged lifecycle callback 4 https://bugs.webkit.org/show_bug.cgi?id=155011 5 6 Reviewed by Antti Koivisto. 7 8 Add basic support for attributeChangedCallback in setAttribute, removeAttribute, setAttributeNS, 9 remoteAttributeNS, setAttributeNode, and removeAttributeNS. There are many other DOM APIs that 10 could modify attributes but we would annotate those APIs in a separate patch to limit the scope 11 of this change. 12 13 In order to invoke the lifecycle callback right before returning to the author script, allocate 14 an instance of CustomElementLifecycleProcessingStack in each of these functions' binding code. 15 The stack object's destructor invokes all callbacks enqueued by the DOM API if there are any. 16 17 Spec: https://w3c.github.io/webcomponents/spec/custom/#dfn-attribute-changed-callback 18 19 Tests: fast/custom-elements/attribute-changed-callback.html 20 fast/custom-elements/lifecycle-callback-timing.html 21 22 * CMakeLists.txt: 23 * WebCore.xcodeproj/project.pbxproj: 24 * bindings/js/JSCustomElementInterface.cpp: 25 (WebCore::JSCustomElementInterface::attributeChanged): Added. Invokes attributeChangedCallback. 26 * bindings/js/JSCustomElementInterface.h: 27 * bindings/js/JSMainThreadExecState.h: 28 (JSMainThreadNullState): Allocate an instance of CustomElementLifecycleProcessingStack in GObject 29 and Objective-C binding code for consistency with JavaScript. We can't do this in JavaScript 30 because there is no RAII object all functions, getters, and setters allocate (for a good reason). 31 32 * bindings/scripts/CodeGeneratorJS.pm: 33 (GenerateImplementation): Generate an instance of CustomElementLifecycleProcessingStack when 34 NeedsLifecycleProcessingStack is specified as an extended IDL attribute. 35 * bindings/scripts/IDLAttributes.txt: Added NeedsLifecycleProcessingStack. 36 * bindings/scripts/test/JS/JSTestObj.cpp: 37 (WebCore::jsTestObjPrototypeFunctionMethodWithNeedsLifecycleProcessingStack): 38 * bindings/scripts/test/TestObj.idl: Added a test for NeedsLifecycleProcessingStack. 39 40 * dom/DOMAllInOne.cpp: 41 * dom/Element.cpp: 42 (WebCore::Element::attributeChanged): Enqueue attributeChanged callback if the context object 43 is a custom element and there is a CustomElementLifecycleProcessingStack allocated in the stack. 44 * dom/Element.idl: 45 46 * dom/LifecycleCallbackQueue.cpp: Added. 47 (WebCore::LifecycleQueueItem): Added. 48 (WebCore::LifecycleQueueItem::LifecycleQueueItem): Added. 49 (WebCore::LifecycleQueueItem::invoke): Added. 50 (WebCore::LifecycleCallbackQueue::LifecycleCallbackQueue): Added. 51 (WebCore::LifecycleCallbackQueue::~LifecycleCallbackQueue): Added. 52 (WebCore::LifecycleCallbackQueue::enqueueAttributeChangedCallback): Added. 53 (WebCore::LifecycleCallbackQueue::invokeAll): Added. 54 (WebCore::CustomElementLifecycleProcessingStack::ensureCurrentQueue): Added. As noted in FIXME, 55 the early exit in the code is necessary only because we haven't added NeedsLifecycleProcessingStack 56 in all places. It should go away in a follow up patch. 57 (WebCore::CustomElementLifecycleProcessingStack::processQueue): Added. 58 * dom/LifecycleCallbackQueue.h: Added. 59 (WebCore::CustomElementLifecycleProcessingStack): This is a light weight RAII object the binding 60 code will allocate in order to queue up lifecycle callbacks. We don't use Ref or std::unique_ptr 61 in m_queue to avoid generating the code to destruct LifecycleCallbackQueue everywhere. 62 (WebCore::CustomElementLifecycleProcessingStack::CustomElementLifecycleProcessingStack): Added. 63 (WebCore::CustomElementLifecycleProcessingStack::~CustomElementLifecycleProcessingStack): Added. 64 (WebCore::CustomElementLifecycleProcessingStack::hasCurrentProcessingStack): Added. 65 1 66 2016-03-04 Carlos Garcia Campos <cgarcia@igalia.com> 2 67 -
trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj
r197596 r197611 4019 4019 9B532EA41BA928570038A827 /* SlotAssignment.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B532EA21BA928570038A827 /* SlotAssignment.h */; }; 4020 4020 9B55EEE91B3E8898005342BC /* EditorCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9B55EEE81B3E8898005342BC /* EditorCocoa.mm */; }; 4021 9B56C9AA1C89329A00C456DF /* LifecycleCallbackQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B56C9A91C89329A00C456DF /* LifecycleCallbackQueue.cpp */; }; 4021 4022 9B69D3B41B98FFE900E3512B /* HTMLSlotElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B69D3B21B98FFE900E3512B /* HTMLSlotElement.cpp */; }; 4022 4023 9B69D3B51B98FFE900E3512B /* HTMLSlotElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B69D3B31B98FFE900E3512B /* HTMLSlotElement.h */; }; … … 11697 11698 9B55EEE81B3E8898005342BC /* EditorCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = EditorCocoa.mm; sourceTree = "<group>"; }; 11698 11699 9B55EEEA1B3F3FEF005342BC /* EditorCocoa.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EditorCocoa.h; sourceTree = "<group>"; }; 11700 9B56C9A81C89312800C456DF /* LifecycleCallbackQueue.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LifecycleCallbackQueue.h; sourceTree = "<group>"; }; 11701 9B56C9A91C89329A00C456DF /* LifecycleCallbackQueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LifecycleCallbackQueue.cpp; sourceTree = "<group>"; }; 11699 11702 9B69D3B11B98FF0A00E3512B /* HTMLSlotElement.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = HTMLSlotElement.idl; sourceTree = "<group>"; }; 11700 11703 9B69D3B21B98FFE900E3512B /* HTMLSlotElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLSlotElement.cpp; sourceTree = "<group>"; }; … … 24324 24327 85031B2E0A44EFC700F992E0 /* KeyboardEvent.h */, 24325 24328 14CF7C2009F7110600EB3665 /* KeyboardEvent.idl */, 24329 9B56C9A91C89329A00C456DF /* LifecycleCallbackQueue.cpp */, 24330 9B56C9A81C89312800C456DF /* LifecycleCallbackQueue.h */, 24326 24331 BC7FA61E0D1F0CBD00DB22A9 /* LiveNodeList.cpp */, 24327 24332 BC7FA61F0D1F0CBD00DB22A9 /* LiveNodeList.h */, … … 29870 29875 977B3872122883E900B81FF8 /* HTMLPreloadScanner.cpp in Sources */, 29871 29876 A43BF5981149290A00C643CA /* HTMLProgressElement.cpp in Sources */, 29877 9B56C9AA1C89329A00C456DF /* LifecycleCallbackQueue.cpp in Sources */, 29872 29878 A8CFF7A50A156978000A4234 /* HTMLQuoteElement.cpp in Sources */, 29873 29879 A8D223FD16B52E4E00157288 /* HTMLResourcePreloader.cpp in Sources */, -
trunk/Source/WebCore/bindings/js/JSCustomElementInterface.cpp
r197463 r197611 102 102 } 103 103 104 void JSCustomElementInterface::attributeChanged(Element& element, const QualifiedName& attributeName, const AtomicString& oldValue, const AtomicString& newValue) 105 { 106 if (!canInvokeCallback()) 107 return; 108 109 Ref<JSCustomElementInterface> protect(*this); 110 111 JSLockHolder lock(m_isolatedWorld->vm()); 112 113 ScriptExecutionContext* context = scriptExecutionContext(); 114 if (!context) 115 return; 116 117 ASSERT(context->isDocument()); 118 JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(context, *m_isolatedWorld); 119 ExecState* state = globalObject->globalExec(); 120 121 JSObject* jsElement = asObject(toJS(state, globalObject, &element)); 122 123 PropertyName attributeChanged(Identifier::fromString(state, "attributeChangedCallback")); 124 JSValue callback = jsElement->get(state, attributeChanged); 125 CallData callData; 126 CallType callType = getCallData(callback, callData); 127 if (callType == CallTypeNone) 128 return; 129 130 const AtomicString& namespaceURI = attributeName.namespaceURI(); 131 MarkedArgumentBuffer args; 132 args.append(jsStringWithCache(state, attributeName.localName())); 133 args.append(oldValue == nullAtom ? jsNull() : jsStringWithCache(state, oldValue)); 134 args.append(newValue == nullAtom ? jsNull() : jsStringWithCache(state, newValue)); 135 args.append(namespaceURI == nullAtom ? jsNull() : jsStringWithCache(state, attributeName.namespaceURI())); 136 137 InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionCall(context, callType, callData); 138 139 NakedPtr<Exception> exception; 140 JSMainThreadExecState::call(state, callback, callType, callData, jsElement, args, exception); 141 142 InspectorInstrumentation::didCallFunction(cookie, context); 143 144 if (exception) 145 reportException(state, exception); 146 } 147 104 148 } // namespace WebCore 105 149 -
trunk/Source/WebCore/bindings/js/JSCustomElementInterface.h
r197463 r197611 51 51 class JSDOMGlobalObject; 52 52 class MathMLElement; 53 class QualifiedName; 53 54 class SVGElement; 54 55 … … 62 63 enum class ShouldClearException { Clear, DoNotClear }; 63 64 RefPtr<Element> constructElement(const AtomicString&, ShouldClearException); 65 66 void attributeChanged(Element&, const QualifiedName&, const AtomicString& oldValue, const AtomicString& newValue); 64 67 65 68 ScriptExecutionContext* scriptExecutionContext() const { return ContextDestructionObserver::scriptExecutionContext(); } -
trunk/Source/WebCore/bindings/js/JSMainThreadExecState.h
r195538 r197611 28 28 29 29 #include "JSDOMBinding.h" 30 #include "LifecycleCallbackQueue.h" 30 31 #include <runtime/Completion.h> 31 32 #include <runtime/Microtask.h> … … 147 148 private: 148 149 JSC::ExecState* m_previousState; 150 #if ENABLE(CUSTOM_ELEMENTS) 151 CustomElementLifecycleProcessingStack m_lifecycleProcessingStack; 152 #endif 149 153 }; 150 154 -
trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
r197353 r197611 2914 2914 $implIncludes{"<runtime/Error.h>"} = 1; 2915 2915 2916 if ($function->signature->extendedAttributes->{"InvokesCustomElementLifecycleCallbacks"}) { 2917 push(@implContent, "#if ENABLE(CUSTOM_ELEMENTS)\n"); 2918 push(@implContent, " CustomElementLifecycleProcessingStack customElementLifecycleProcessingStack;\n"); 2919 push(@implContent, "#endif\n"); 2920 $implIncludes{"LifecycleCallbackQueue.h"} = 1; 2921 } 2922 2916 2923 if ($function->isStatic) { 2917 2924 if ($isCustom) { -
trunk/Source/WebCore/bindings/scripts/IDLAttributes.txt
r197353 r197611 92 92 MasqueradesAsUndefined 93 93 NamedConstructor=* 94 InvokesCustomElementLifecycleCallbacks 94 95 NewImpurePropertyFiresWatchpoints 95 96 NewObject -
trunk/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp
r197353 r197611 46 46 #include "JSTestSubObj.h" 47 47 #include "JSbool.h" 48 #include "LifecycleCallbackQueue.h" 48 49 #include "SVGDocument.h" 49 50 #include "SVGPoint.h" … … 186 187 JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionTestPromiseFunctionWithException(JSC::ExecState*); 187 188 JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionTestPromiseFunctionWithOptionalIntArgument(JSC::ExecState*); 189 JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithNeedsLifecycleProcessingStack(JSC::ExecState*); 188 190 JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionSymbolIterator(JSC::ExecState*); 189 191 JSC::EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionEntries(JSC::ExecState*); … … 714 716 { "testPromiseFunctionWithException", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionTestPromiseFunctionWithException), (intptr_t) (0) } }, 715 717 { "testPromiseFunctionWithOptionalIntArgument", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionTestPromiseFunctionWithOptionalIntArgument), (intptr_t) (0) } }, 718 { "methodWithNeedsLifecycleProcessingStack", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionMethodWithNeedsLifecycleProcessingStack), (intptr_t) (0) } }, 716 719 { "entries", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionEntries), (intptr_t) (0) } }, 717 720 { "keys", JSC::Function, NoIntrinsic, { (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionKeys), (intptr_t) (0) } }, … … 5022 5025 } 5023 5026 5027 EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionMethodWithNeedsLifecycleProcessingStack(ExecState* state) 5028 { 5029 #if ENABLE(CUSTOM_ELEMENTS) 5030 CustomElementLifecycleProcessingStack customElementLifecycleProcessingStack; 5031 #endif 5032 JSValue thisValue = state->thisValue(); 5033 auto castedThis = jsDynamicCast<JSTestObj*>(thisValue); 5034 if (UNLIKELY(!castedThis)) 5035 return throwThisTypeError(*state, "TestObj", "methodWithNeedsLifecycleProcessingStack"); 5036 ASSERT_GC_OBJECT_INHERITS(castedThis, JSTestObj::info()); 5037 auto& impl = castedThis->wrapped(); 5038 impl.methodWithNeedsLifecycleProcessingStack(); 5039 return JSValue::encode(jsUndefined()); 5040 } 5041 5024 5042 using TestObjIterator = JSKeyValueIterator<JSTestObj>; 5025 5043 using TestObjIteratorPrototype = JSKeyValueIteratorPrototype<JSTestObj>; -
trunk/Source/WebCore/bindings/scripts/test/TestObj.idl
r197353 r197611 333 333 [PutForwards=name] readonly attribute TestNode putForwardsAttribute; 334 334 [PutForwards=name] readonly attribute TestNode? putForwardsNullableAttribute; 335 336 #if defined(TESTING_JS) 337 [NeedsLifecycleProcessingStack] void methodWithNeedsLifecycleProcessingStack(); 338 #endif 335 339 }; 336 340 -
trunk/Source/WebCore/dom/DOMAllInOne.cpp
r193286 r197611 94 94 #include "InlineStyleSheetOwner.cpp" 95 95 #include "KeyboardEvent.cpp" 96 #include "LifecycleCallbackQueue.cpp" 96 97 #include "LiveNodeList.cpp" 97 98 #include "MessageChannel.cpp" -
trunk/Source/WebCore/dom/Element.cpp
r197478 r197611 38 38 #include "ComposedTreeAncestorIterator.h" 39 39 #include "ContainerNodeAlgorithms.h" 40 #include "CustomElementDefinitions.h" 40 41 #include "DOMTokenList.h" 41 42 #include "Dictionary.h" … … 62 63 #include "JSLazyEventListener.h" 63 64 #include "KeyboardEvent.h" 65 #include "LifecycleCallbackQueue.h" 64 66 #include "MainFrame.h" 65 67 #include "MutationObserverInterestGroup.h" … … 1263 1265 document().incDOMTreeVersion(); 1264 1266 1267 #if ENABLE(CUSTOM_ELEMENTS) 1268 if (UNLIKELY(isCustomElement())) { 1269 auto* definitions = document().customElementDefinitions(); 1270 auto* interface = definitions->findInterface(tagQName()); 1271 RELEASE_ASSERT(interface); 1272 LifecycleCallbackQueue::enqueueAttributeChangedCallback(*this, *interface, name, oldValue, newValue); 1273 } 1274 #endif 1275 1265 1276 if (valueIsSameAsBefore) 1266 1277 return; -
trunk/Source/WebCore/dom/Element.idl
r197353 r197611 29 29 30 30 DOMString? getAttribute([Default=Undefined] optional DOMString name); 31 [ObjCLegacyUnnamedParameters, RaisesException] void setAttribute([Default=Undefined] optional DOMString name, 32 [Default=Undefined] optional DOMString value); 33 void removeAttribute([Default=Undefined] optional DOMString name); 31 32 [ObjCLegacyUnnamedParameters, RaisesException, InvokesCustomElementLifecycleCallbacks] 33 void setAttribute([Default=Undefined] optional DOMString name, [Default=Undefined] optional DOMString value); 34 35 [InvokesCustomElementLifecycleCallbacks] void removeAttribute([Default=Undefined] optional DOMString name); 34 36 Attr getAttributeNode([Default=Undefined] optional DOMString name); 35 [RaisesException ] Attr setAttributeNode([Default=Undefined] optional Attr newAttr);36 [RaisesException ] Attr removeAttributeNode([Default=Undefined] optional Attr oldAttr);37 [RaisesException, InvokesCustomElementLifecycleCallbacks] Attr setAttributeNode([Default=Undefined] optional Attr newAttr); 38 [RaisesException, InvokesCustomElementLifecycleCallbacks] Attr removeAttributeNode([Default=Undefined] optional Attr oldAttr); 37 39 38 40 #if defined(LANGUAGE_OBJECTIVE_C) && LANGUAGE_OBJECTIVE_C … … 51 53 52 54 [ObjCLegacyUnnamedParameters] DOMString? getAttributeNS([Default=Undefined] optional DOMString? namespaceURI, [Default=Undefined] optional DOMString localName); 53 [ObjCLegacyUnnamedParameters, RaisesException] void setAttributeNS([Default=Undefined] optional DOMString? namespaceURI, 54 [Default=Undefined] optional DOMString qualifiedName, 55 [Default=Undefined] optional DOMString value); 56 [ObjCLegacyUnnamedParameters] void removeAttributeNS(DOMString? namespaceURI, DOMString localName); 55 56 [ObjCLegacyUnnamedParameters, RaisesException, InvokesCustomElementLifecycleCallbacks] 57 void setAttributeNS([Default=Undefined] optional DOMString? namespaceURI, 58 [Default=Undefined] optional DOMString qualifiedName, [Default=Undefined] optional DOMString value); 59 60 [ObjCLegacyUnnamedParameters, InvokesCustomElementLifecycleCallbacks] void removeAttributeNS(DOMString? namespaceURI, DOMString localName); 57 61 58 62 #if defined(LANGUAGE_OBJECTIVE_C) && LANGUAGE_OBJECTIVE_C … … 62 66 #endif 63 67 [ObjCLegacyUnnamedParameters] Attr getAttributeNodeNS([Default=Undefined] optional DOMString? namespaceURI, [Default=Undefined] optional DOMString localName); 64 [RaisesException ] Attr setAttributeNodeNS([Default=Undefined] optional Attr newAttr);68 [RaisesException, InvokesCustomElementLifecycleCallbacks] Attr setAttributeNodeNS([Default=Undefined] optional Attr newAttr); 65 69 boolean hasAttribute(DOMString name); 66 70 [ObjCLegacyUnnamedParameters] boolean hasAttributeNS([Default=Undefined] optional DOMString? namespaceURI, [Default=Undefined] optional DOMString localName);
Note: See TracChangeset
for help on using the changeset viewer.