RESOLVED FIXED Bug 189034
for/in over a Proxy should not call [[GetOwnProperty]] trap twice per property
https://bugs.webkit.org/show_bug.cgi?id=189034
Summary for/in over a Proxy should not call [[GetOwnProperty]] trap twice per property
Kevin Gibbons
Reported 2018-08-27 16:36:11 PDT
Consider the following program: ``` if (typeof console === 'undefined') console = { log: print }; let a = Object.create(null, { x: { enumerable: false, configurable: true, value: 0 }, }); let handler = { getOwnPropertyDescriptor(t, p) { console.log('gopd'); let o = Reflect.getOwnPropertyDescriptor(t, p); o.enumerable = true; return o; }, }; let pa = new Proxy(a, handler); for (let key in pa) { console.log('reached'); } ``` This prints nothing. It should print `gopd` and `reached`, like every other browser. The spec, in #sec-enumerate-object-properties, requires that for-in enumeration determines enumerability by calling [[GetOwnProperty]], which on proxies means an observable invocation of the getOwnPropertyDescriptor trap. JSC appears to be relying on the enumerability of the target's property directly, which is bad. This only happens if the `ownKeys` handler is not present, even with the default behavior. That is, adding `ownKeys(target) { return Reflect.ownKeys(target); },` to the proxy's handler causes the program to behave correctly. See also https://bugs.webkit.org/show_bug.cgi?id=189030. These two might have the same root cause - from the observable behavior, it looks like some code is assuming that `ownKeys` only returns enumerable properties, which is not its behavior (even in JSC). See also (and please comment on) this open spec bug about more precisely specifying the behavior of for-in, which prompted the investigation which lead me to discovering these issues: https://github.com/tc39/ecma262/issues/1281
Attachments
Patch (14.67 KB, patch)
2019-04-19 18:39 PDT, Caitlin Potter (:caitp)
no flags
Archive of layout-test-results from ews105 for mac-highsierra-wk2 (3.94 MB, application/zip)
2019-04-19 19:34 PDT, EWS Watchlist
no flags
Archive of layout-test-results from ews103 for mac-highsierra (3.26 MB, application/zip)
2019-04-19 19:44 PDT, EWS Watchlist
no flags
Archive of layout-test-results from ews124 for ios-simulator-wk2 (2.81 MB, application/zip)
2019-04-19 20:37 PDT, EWS Watchlist
no flags
Archive of layout-test-results from ews206 for win-future (13.07 MB, application/zip)
2019-04-19 22:44 PDT, EWS Watchlist
no flags
Patch (8.58 KB, patch)
2021-01-07 20:38 PST, Alexey Shvayka
no flags
Caitlin Potter (:caitp)
Comment 1 2019-02-22 10:51:34 PST
Caitlin Potter (:caitp)
Comment 2 2019-04-19 18:20:39 PDT
My earlier comment was incorrect (as was pointed out elsewhere) --- I've written a fix for this, which I think is complete. I'd like to run it on EWS, and if everything is green, I believe it will allow the complete removal of op_has_indexed_property, op_has_structure_property and op_has_generic_property (which AFAIK are not used by anything other than ForIn loops).
Caitlin Potter (:caitp)
Comment 3 2019-04-19 18:39:42 PDT
EWS Watchlist
Comment 4 2019-04-19 19:34:40 PDT Comment hidden (obsolete)
EWS Watchlist
Comment 5 2019-04-19 19:34:42 PDT Comment hidden (obsolete)
EWS Watchlist
Comment 6 2019-04-19 19:44:14 PDT Comment hidden (obsolete)
EWS Watchlist
Comment 7 2019-04-19 19:44:16 PDT Comment hidden (obsolete)
EWS Watchlist
Comment 8 2019-04-19 20:37:28 PDT Comment hidden (obsolete)
EWS Watchlist
Comment 9 2019-04-19 20:37:30 PDT Comment hidden (obsolete)
jsc-armv7 EWS
Comment 10 2019-04-19 21:28:48 PDT Comment hidden (obsolete)
Caitlin Potter (:caitp)
Comment 11 2019-04-19 21:31:55 PDT
Ah, re-reading the spec, this isn't quite going to work, since For-In can't eagerly check the property descriptor immediately after [[OwnPropertyKeys]] :\ Will have to figure out another way. Ignore the R=? for now.
EWS Watchlist
Comment 12 2019-04-19 22:44:10 PDT Comment hidden (obsolete)
EWS Watchlist
Comment 13 2019-04-19 22:44:10 PDT Comment hidden (obsolete)
EWS Watchlist
Comment 14 2019-04-19 22:44:22 PDT Comment hidden (obsolete)
EWS Watchlist
Comment 15 2019-04-20 01:42:47 PDT Comment hidden (obsolete)
Alexey Shvayka
Comment 16 2021-01-07 20:38:06 PST
Alexey Shvayka
Comment 17 2021-01-07 20:41:36 PST
(In reply to Alexey Shvayka from comment #16) > Created attachment 417241 [details] > Patch r271191 patch for-in-proxy 134.0518+-2.8758 ^ 66.2318+-1.0129 ^ definitely 2.0240x faster <geometric> 134.0518+-2.8758 ^ 66.2318+-1.0129 ^ definitely 2.0240x faster
Alexey Shvayka
Comment 18 2021-01-07 20:48:24 PST
(In reply to Caitlin Potter (:caitp) from comment #3) > Created attachment 367860 [details] > Patch This patch gets a lot things right: 1. JSModuleNamespaceObject.cpp change was landed as-is in r254390. 2. A bit different approach to fixing ProxyObject.cpp was landed in r254070. 3. proxy-for-in.js stress test will be landed as-is in the new patch. Thanks Caitlin!
Yusuke Suzuki
Comment 19 2021-01-08 10:48:43 PST
Comment on attachment 417241 [details] Patch r=me
EWS
Comment 20 2021-01-08 10:52:32 PST
Committed r271305: <https://trac.webkit.org/changeset/271305> All reviewed patches have been landed. Closing bug and clearing flags on attachment 417241 [details].
Radar WebKit Bug Importer
Comment 21 2021-01-08 10:53:19 PST
Note You need to log in before you can comment on or make changes to this bug.