WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
137651
WeakMap reference w/ DOM element as key does not survive long enough
https://bugs.webkit.org/show_bug.cgi?id=137651
Summary
WeakMap reference w/ DOM element as key does not survive long enough
Tim Guan-tin Chien [:timdream]
Reported
2014-10-12 19:35:28 PDT
STR: 1. Open the reduced test case, open up the Inspector 2. Click Run 3. Observer the console output Expected: 1. console keep printing the object from our setInterval call Actual: 1. After GC (?) the console start to porint out 'undefined' Note: Originally submitted as:
https://github.com/timdream/gaia-keyboard-demo/issues/7
This is easier to reproduce on iOS 8 Simulator than on Safari 7.1, and harder on WebKit Nightly. Does not affect previous iOS or Safari versions because WeakMap was not implemented.
Attachments
Testcase
(492 bytes, text/html)
2014-10-12 19:36 PDT
,
Tim Guan-tin Chien [:timdream]
no flags
Details
The patch
(6.91 KB, patch)
2015-05-29 11:52 PDT
,
Keith Miller
ggaren
: review-
ggaren
: commit-queue-
Details
Formatted Diff
Diff
Patch 2
(296.44 KB, patch)
2015-05-29 13:32 PDT
,
Keith Miller
ggaren
: review-
ggaren
: commit-queue-
Details
Formatted Diff
Diff
Patch Nomenclature
(7.05 KB, patch)
2015-05-29 16:21 PDT
,
Keith Miller
ggaren
: review-
ggaren
: commit-queue-
Details
Formatted Diff
Diff
Patch Added Expected
(7.52 KB, patch)
2015-05-29 16:34 PDT
,
Keith Miller
no flags
Details
Formatted Diff
Diff
Patch Expected File
(7.52 KB, patch)
2015-05-29 16:35 PDT
,
Keith Miller
no flags
Details
Formatted Diff
Diff
Show Obsolete
(4)
View All
Add attachment
proposed patch, testcase, etc.
Tim Guan-tin Chien [:timdream]
Comment 1
2014-10-12 19:36:15 PDT
Created
attachment 239710
[details]
Testcase
Radar WebKit Bug Importer
Comment 2
2014-10-13 23:09:38 PDT
<
rdar://problem/18645174
>
Geoffrey Garen
Comment 3
2014-10-14 11:53:04 PDT
In this test case, the JavaScript wrapper for the p element is garbage collected because there are no explicit references to it -- even though its underlying C++ DOM object is still present in the document. I guess the behavior you expected was for the JavaScript wrapper's lifetime to be identical to its underlying DOM object, as observed by a WeakMap. Ironically, implementing that feature would require a WeakMap to strongly reference a DOM object. I'm not sure what the correct behavior is in this case. Perhaps the optimization to throw away unobservable DOM wrappers is invalid in a world where WeakMap can observe the lifetime of any object.
Tim Guan-tin Chien [:timdream]
Comment 4
2014-10-14 19:18:34 PDT
Thanks for the comment, (In reply to
comment #3
)
> In this test case, the JavaScript wrapper for the p element is garbage collected because there are no explicit references to it -- even though its underlying C++ DOM object is still present in the document. >
Web Developers shouldn't be worry about how the DOM object is implemented right :) ?
> I guess the behavior you expected was for the JavaScript wrapper's lifetime to be identical to its underlying DOM object, as observed by a WeakMap. > > Ironically, implementing that feature would require a WeakMap to strongly reference a DOM object. > > I'm not sure what the correct behavior is in this case. Perhaps the optimization to throw away unobservable DOM wrappers is invalid in a world where WeakMap can observe the lifetime of any object.
FWIW Gecko and Chrome does not fail when I run this test case.
Alexey Proskuryakov
Comment 5
2014-10-14 22:16:44 PDT
I think that adding a custom property on each node in WeakMap may be a reasonable workaround. Geoff, does this have any serious downsides? while (i--) { document.body.appendChild(document.createElement('p')); document.body.lastElementChild.textContent = i; document.body.lastElementChild.webkitWeakMapWorkaround = 1; // <-- This wmap.set(document.body.lastElementChild, { foo: 'bar', id: i }); } Perhaps we can use a similar mechanism to make WeakMap work with nodes. Possibly a side HashCountedSet, or even a counter in node rare data.
Geoffrey Garen
Comment 6
2014-10-15 12:13:33 PDT
> I think that adding a custom property on each node in WeakMap may be a reasonable workaround. Geoff, does this have any serious downsides? > > while (i--) { > document.body.appendChild(document.createElement('p')); > document.body.lastElementChild.textContent = i; > document.body.lastElementChild.webkitWeakMapWorkaround = 1; // <-- This > wmap.set(document.body.lastElementChild, { foo: 'bar', id: i }); > }
I think that's a reasonable workaround.
> Perhaps we can use a similar mechanism to make WeakMap work with nodes. Possibly a side HashCountedSet, or even a counter in node rare data.
I think we could. Ultimately, though, it might just be time to retire the "unobservable wrapper" optimization. Now that WeakMap and WeakSet expose GC semantics, everything is logically observable.
Alexey Proskuryakov
Comment 7
2014-10-15 12:44:08 PDT
> even a counter in node rare data
Geoff pointed out that this won't work, because we likely have the same issue with some non-node objects (such as probably CSS OM).
> Now that WeakMap and WeakSet expose GC semantics
I don't think that they do - there is no way to iterate them, so you always need a reachable object for lookup.
Geoffrey Garen
Comment 8
2014-10-15 13:59:13 PDT
> > Now that WeakMap and WeakSet expose GC semantics > > I don't think that they do - there is no way to iterate them, so you always need a reachable object for lookup.
What I mean by this is that the expose, in a programmer-visible way for the first-time, whether the engine decided to garbage collect a JavaScript wrapper that was not visible through any other API.
Joseph Pecoraro
Comment 9
2015-04-22 13:42:40 PDT
I just ran into this with WeakSet. It was unexpected to me to see a node disappear from a WeakSet. It is inconvenient and unexpected to have to work around this.
Keith Miller
Comment 10
2015-05-29 11:52:56 PDT
Created
attachment 253904
[details]
The patch
Filip Pizlo
Comment 11
2015-05-29 12:01:56 PDT
Comment on
attachment 253904
[details]
The patch View in context:
https://bugs.webkit.org/attachment.cgi?id=253904&action=review
> Source/WebCore/bindings/js/JSNodeCustom.cpp:79 > -static inline bool isObservable(JSNode* jsNode, Node* node) > -{ > - // The root node keeps the tree intact. > - if (!node->parentNode()) > - return true; > - > - if (jsNode->hasCustomProperties()) > - return true; > - > - // A node's JS wrapper is responsible for marking its JS event listeners. > - if (node->hasEventListeners()) > - return true; > - > - return false; > -} > - > -static inline bool isReachableFromDOM(JSNode* jsNode, Node* node, SlotVisitor& visitor) > +static inline bool isReachableFromDOM(Node* node, SlotVisitor& visitor)
Hmmm, it seems like we should do some performance tests to make sure that this isn't too severe.
Geoffrey Garen
Comment 12
2015-05-29 12:16:33 PDT
Comment on
attachment 253904
[details]
The patch Please add a comment in your ChangeLog to explain your performance testing methodology.
Keith Miller
Comment 13
2015-05-29 13:32:26 PDT
Created
attachment 253909
[details]
Patch 2 Updated the ChangeLog to reflect the performance testing strategy for this patch.
Geoffrey Garen
Comment 14
2015-05-29 14:39:06 PDT
Comment on
attachment 253909
[details]
Patch 2 View in context:
https://bugs.webkit.org/attachment.cgi?id=253909&action=review
Looks like you have some accidental whitespace changes throughout the ChangeLog. Did you reflow the document?
> Source/WebCore/ChangeLog:11 > + will be done after the code is rolled out. If major > + performance issues occur the patch will be rolled back.
We use "rolled out" to mean removing the patch. So, you are going to test by monitor bots after committing the change, and then you will roll out if there is a problem.
Keith Miller
Comment 15
2015-05-29 16:21:39 PDT
Created
attachment 253929
[details]
Patch Nomenclature Undid the whitespace problem and changed the wording to be in line with the rest of the team.
Geoffrey Garen
Comment 16
2015-05-29 16:23:57 PDT
Comment on
attachment 253929
[details]
Patch Nomenclature Oops! Didn't notice this before: Regression test needs expected results.
Keith Miller
Comment 17
2015-05-29 16:34:20 PDT
Created
attachment 253933
[details]
Patch Added Expected Added the expected test results file.
Keith Miller
Comment 18
2015-05-29 16:35:37 PDT
Created
attachment 253934
[details]
Patch Expected File
Geoffrey Garen
Comment 19
2015-05-29 16:36:58 PDT
Comment on
attachment 253934
[details]
Patch Expected File r=me
WebKit Commit Bot
Comment 20
2015-05-29 17:27:03 PDT
Comment on
attachment 253934
[details]
Patch Expected File Clearing flags on attachment: 253934 Committed
r185023
: <
http://trac.webkit.org/changeset/185023
>
WebKit Commit Bot
Comment 21
2015-05-29 17:27:07 PDT
All reviewed patches have been landed. Closing bug.
Alexey Proskuryakov
Comment 22
2015-05-29 19:46:39 PDT
This broke bindings tests, which need to be updated. Is anyone around to do that now? I can only do it later in the evening.
Joseph Pecoraro
Comment 23
2015-05-29 20:52:23 PDT
Bindings test updated:
http://trac.webkit.org/changeset/185029
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug