Bug 218363

Summary: Promises returned by our DOM API have the caller's global instead of the callee's
Product: WebKit Reporter: Chris Dumez <cdumez>
Component: BindingsAssignee: Chris Dumez <cdumez>
Status: RESOLVED FIXED    
Severity: Normal CC: cdumez, clopez, darin, eric.carlson, esprehn+autocc, ews-watchlist, ggaren, glenn, jer.noble, kangil.han, philipj, rniwa, sam, sergio, webkit-bug-importer, youennf, ysuzuki
Priority: P2 Keywords: InRadar
Version: WebKit Nightly Build   
Hardware: Unspecified   
OS: Unspecified   
See Also: https://bugs.webkit.org/show_bug.cgi?id=218361
https://bugs.webkit.org/show_bug.cgi?id=218455
https://bugs.webkit.org/show_bug.cgi?id=219019
https://bugs.webkit.org/show_bug.cgi?id=234867
Bug Depends on: 218468, 218474    
Bug Blocks:    
Attachments:
Description Flags
WIP Patch
none
WIP Patch
ews-feeder: commit-queue-
WIP Patch
none
WIP Patch
none
WIP Patch
none
WIP Patch
none
Patch
none
Patch
none
Patch
none
Patch
none
Patch
none
Patch none

Chris Dumez
Reported 2020-10-29 16:31:51 PDT
Promises returns by our DOM API have the caller's global instead of the callee's. This is inconsistent with Blink and Gecko. As a result, the values passed when resolving those promises also end up with the wrong global object.
Attachments
WIP Patch (5.85 KB, patch)
2020-10-29 16:33 PDT, Chris Dumez
no flags
WIP Patch (7.04 KB, patch)
2020-10-29 16:54 PDT, Chris Dumez
ews-feeder: commit-queue-
WIP Patch (91.63 KB, patch)
2020-10-30 08:27 PDT, Chris Dumez
no flags
WIP Patch (95.21 KB, patch)
2020-10-30 09:12 PDT, Chris Dumez
no flags
WIP Patch (95.29 KB, patch)
2020-10-30 09:17 PDT, Chris Dumez
no flags
WIP Patch (98.56 KB, patch)
2020-10-30 09:25 PDT, Chris Dumez
no flags
Patch (109.21 KB, patch)
2020-10-30 10:22 PDT, Chris Dumez
no flags
Patch (110.05 KB, patch)
2020-10-30 13:42 PDT, Chris Dumez
no flags
Patch (110.15 KB, patch)
2020-10-30 16:17 PDT, Chris Dumez
no flags
Patch (111.29 KB, patch)
2020-10-30 16:59 PDT, Chris Dumez
no flags
Patch (111.94 KB, patch)
2020-10-30 23:15 PDT, Chris Dumez
no flags
Patch (110.42 KB, patch)
2020-10-30 23:18 PDT, Chris Dumez
no flags
Chris Dumez
Comment 1 2020-10-29 16:33:02 PDT
Created attachment 412698 [details] WIP Patch
Chris Dumez
Comment 2 2020-10-29 16:47:24 PDT
Comment on attachment 412698 [details] WIP Patch View in context: https://bugs.webkit.org/attachment.cgi?id=412698&action=review > Source/WebCore/dom/Document.cpp:2715 > + m_documentTaskGroup->stopAndDiscardAllTasks();*/ I need to look into this more and talk to Ryosuke but I think we may want a group per top document, rather than a group per document. This way, we would still discard all tasks on navigation.
Chris Dumez
Comment 3 2020-10-29 16:54:46 PDT
Created attachment 412699 [details] WIP Patch
Chris Dumez
Comment 4 2020-10-30 08:27:50 PDT
Created attachment 412746 [details] WIP Patch
Chris Dumez
Comment 5 2020-10-30 09:12:39 PDT
Created attachment 412752 [details] WIP Patch
Chris Dumez
Comment 6 2020-10-30 09:17:03 PDT
Created attachment 412753 [details] WIP Patch
EWS Watchlist
Comment 7 2020-10-30 09:18:03 PDT
This patch modifies the imported WPT tests. Please ensure that any changes on the tests (not coming from a WPT import) are exported to WPT. Please see https://trac.webkit.org/wiki/WPTExportProcess
Chris Dumez
Comment 8 2020-10-30 09:25:59 PDT
Created attachment 412755 [details] WIP Patch
Chris Dumez
Comment 9 2020-10-30 10:22:56 PDT
Chris Dumez
Comment 10 2020-10-30 13:42:05 PDT
Darin Adler
Comment 11 2020-10-30 16:06:13 PDT
Comment on attachment 412792 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=412792&action=review > Source/WebCore/bindings/js/JSDOMPromiseDeferred.h:317 > + auto& globalObject = *JSC::jsCast<JSDOMGlobalObject*>(&lexicalGlobalObject); What guarantees this? I guess maybe it’s obvious, but I wasn’t sure. > Source/WebCore/bindings/js/JSDOMPromiseDeferred.h:336 > + auto& globalObject = *JSC::jsCast<JSDOMGlobalObject*>(&lexicalGlobalObject); Ditto. > Source/WebCore/dom/EventLoop.cpp:82 > + auto associatedGroup = std::exchange(m_associatedGroups, { }); Should be plural, associatedGroups. > Source/WebCore/dom/EventLoop.h:140 > + m_isReadyToStop = true; > + if (m_eventLoop) > + m_eventLoop->stopAssociatedGroupsIfNecessary(); Is it correct to call stopAssociatedGroupsIfNecessary even if m_isReadyToStop was already true?
Chris Dumez
Comment 12 2020-10-30 16:10:47 PDT
Comment on attachment 412792 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=412792&action=review >> Source/WebCore/bindings/js/JSDOMPromiseDeferred.h:317 >> + auto& globalObject = *JSC::jsCast<JSDOMGlobalObject*>(&lexicalGlobalObject); > > What guarantees this? I guess maybe it’s obvious, but I wasn’t sure. I will confirm with Geoff. >> Source/WebCore/dom/EventLoop.cpp:82 >> + auto associatedGroup = std::exchange(m_associatedGroups, { }); > > Should be plural, associatedGroups. Oops. Will fix. >> Source/WebCore/dom/EventLoop.h:140 >> + m_eventLoop->stopAssociatedGroupsIfNecessary(); > > Is it correct to call stopAssociatedGroupsIfNecessary even if m_isReadyToStop was already true? I don't see how it would hurt. stopAssociatedGroupsIfNecessary() would iterate though all the groups again and check if all groups are ready to stop. Seems like a good idea to early return though to avoid doing work unnecessarily.
Chris Dumez
Comment 13 2020-10-30 16:14:34 PDT
(In reply to Chris Dumez from comment #12) > Comment on attachment 412792 [details] > Patch > > View in context: > https://bugs.webkit.org/attachment.cgi?id=412792&action=review > > >> Source/WebCore/bindings/js/JSDOMPromiseDeferred.h:317 > >> + auto& globalObject = *JSC::jsCast<JSDOMGlobalObject*>(&lexicalGlobalObject); > > > > What guarantees this? I guess maybe it’s obvious, but I wasn’t sure. > > I will confirm with Geoff. FYI, we used to call callerGlobalObject() which was casting similarly internally, so I figured I did not make thing worse: JSDOMGlobalObject& callerGlobalObject(JSGlobalObject& lexicalGlobalObject, CallFrame& callFrame) { class GetCallerGlobalObjectFunctor { public: GetCallerGlobalObjectFunctor() = default; StackVisitor::Status operator()(StackVisitor& visitor) const { if (!m_hasSkippedFirstFrame) { m_hasSkippedFirstFrame = true; return StackVisitor::Continue; } if (auto* codeBlock = visitor->codeBlock()) m_globalObject = codeBlock->globalObject(); else { ASSERT(visitor->callee().rawPtr()); // FIXME: Callee is not an object if the caller is Web Assembly. // Figure out what to do here. We can probably get the global object // from the top-most Wasm Instance. https://bugs.webkit.org/show_bug.cgi?id=165721 if (visitor->callee().isCell() && visitor->callee().asCell()->isObject()) m_globalObject = jsCast<JSObject*>(visitor->callee().asCell())->globalObject(); } return StackVisitor::Done; } JSGlobalObject* globalObject() const { return m_globalObject; } private: mutable bool m_hasSkippedFirstFrame { false }; mutable JSGlobalObject* m_globalObject { nullptr }; }; GetCallerGlobalObjectFunctor iter; callFrame.iterate(lexicalGlobalObject.vm(), iter); if (iter.globalObject()) return *jsCast<JSDOMGlobalObject*>(iter.globalObject()); // If we cannot find JSGlobalObject in caller frames, we just return the current lexicalGlobalObject. return *jsCast<JSDOMGlobalObject*>(&lexicalGlobalObject); }
Chris Dumez
Comment 14 2020-10-30 16:17:20 PDT
Ryosuke Niwa
Comment 15 2020-10-30 16:44:00 PDT
Comment on attachment 412807 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=412807&action=review > Source/WebCore/dom/EventLoop.h:117 > + if (m_eventLoop) > + m_eventLoop->unregisterGroup(*this); Can we avoid de-referencing m_eventLoop twice here? > Source/WebCore/dom/EventLoop.h:143 > + if (m_eventLoop) > + m_eventLoop->stopAssociatedGroupsIfNecessary(); Ditto. > Source/WebCore/dom/EventLoop.h:189 > State m_state { State::Running }; > + bool m_isReadyToStop { false }; Please just add a new value to State instead of adding a new boolean.
Chris Dumez
Comment 16 2020-10-30 16:53:25 PDT
(In reply to Ryosuke Niwa from comment #15) > Comment on attachment 412807 [details] > Patch > > View in context: > https://bugs.webkit.org/attachment.cgi?id=412807&action=review > > > Source/WebCore/dom/EventLoop.h:117 > > + if (m_eventLoop) > > + m_eventLoop->unregisterGroup(*this); > > Can we avoid de-referencing m_eventLoop twice here? > > > Source/WebCore/dom/EventLoop.h:143 > > + if (m_eventLoop) > > + m_eventLoop->stopAssociatedGroupsIfNecessary(); > > Ditto. > > > Source/WebCore/dom/EventLoop.h:189 > > State m_state { State::Running }; > > + bool m_isReadyToStop { false }; > > Please just add a new value to State instead of adding a new boolean. Will fix.
Chris Dumez
Comment 17 2020-10-30 16:59:20 PDT
Chris Dumez
Comment 18 2020-10-30 16:59:59 PDT
*** Bug 218361 has been marked as a duplicate of this bug. ***
Chris Dumez
Comment 19 2020-10-30 23:15:12 PDT
Chris Dumez
Comment 20 2020-10-30 23:18:09 PDT
EWS
Comment 21 2020-10-31 09:12:04 PDT
Committed r269227: <https://trac.webkit.org/changeset/269227> All reviewed patches have been landed. Closing bug and clearing flags on attachment 412835 [details].
Radar WebKit Bug Importer
Comment 22 2020-10-31 09:13:22 PDT
Note You need to log in before you can comment on or make changes to this bug.