Bug: Reflect.ownKeys(function() {}) differs in V8 strict mode than other cases
The part that matters here is in annex B: www.ecma-international.org/ecma-262/7.0/#sec-forbidden-extensions
This forbids functions in strict code from having own properties "caller" or "arguments". Newer function kinds have these restrictions in sloppy mode.
AddRestricted... adds the accessor which makes getting/setting "caller" or "arguments" throw, but is per spec only performed on intrinsics (like %FunctionPrototype%).
So unfortunately, this is something your membrane would need to be aware of and work around. Mozilla's approach violates ECMAScript's forbidden extensions and can't be considered "correct"
Sent from my iPhone
Mozilla's approach violates ECMAScript's forbidden extensions and can't be considered "correct"
Why? The spec forbids adding "caller" or "arguments" in strict mode. I think it does not enforce adding them in sloppy mode.
Chrome seems to add them only in sloppy mode, and Firefox to never add them. So I think both follow the spec.
Besides those two, the only other reference to AddRestrictedFunctionProperties is < www.ecma-international.org/ecma-262/7.0/#sec-createintrinsics>
step 12:
- Perform AddRestrictedFunctionProperties www.ecma-international.org/ecma-262/7.0/#sec-addrestrictedfunctionproperties (funcProto, realmRec).
So .caller and .arguments must now exist as poisoned on (the intrinsic normally bound to) Function.prototype . So, besides Function.prototype, they may only appear on old-style sloppy functions; nowhere else.
On Mon, Sep 5, 2016 at 6:09 PM, Caitlin Potter <caitpotter88 at gmail.com>
wrote:
The part that matters here is in annex B: http://www.ecma- international.org/ecma-262/7.0/#sec-forbidden-extensions
This forbids functions in strict code from having own properties "caller" or "arguments". Newer function kinds have these restrictions in sloppy mode.
AddRestricted... adds the accessor which makes getting/setting "caller" or "arguments" throw, but is per spec only performed on intrinsics (like %FunctionPrototype%).
So unfortunately, this is something your membrane would need to be aware of and work around. Mozilla's approach violates ECMAScript's forbidden extensions and can't be considered "correct"
This result by itself does not demonstrate that Mozilla or v8 are either conformant or non-conformant. By the spec, A must not have its own .caller and .arguments -- it must only inherit these from Function.prototype. B, being sloppy, may or may not.
Web compat enforces adding them in sloppy mode. My understanding of what he’s saying is that V8 “incorrectly” omits these own properties from strict functions, which is correct per spec.
Ah, my bad, you’re right — they only expose the accessors on the prototype, so they’re in the clear. But yeah, there’s no requirement one way or the other (other than re: web compat) for the properties being there in sloppy mode.
Ugh!! It's a trap! (In the Star Wars sense, not the proxy sense.)
So if all my code is in strict mode, and I get a non-strict code function to shadow as Tom and I were talking about in another thread... how do I even test for that if my code is either consistently strict or consistently non-strict?
So if all my code is in strict mode, and I get a non-strict code function to shadow as Tom and I were talking about in another thread... how do I even test for that if my code is either consistently strict or consistently non-strict?
Don't check that. The target could have other non-configurable properties added by the user anyway.
So just include the non-configurable own properties of the target in the property list returned by the trap.
Also consider using your own function as the target instead of the function provided by the user. This way you can be sure it will be a strict mode function, it will be extensible, and won't have any additional non-configurable own property. Then you will have less problems with proxy invariants.
Based on your feedback, I've filed bugzilla.mozilla.org/show_bug.cgi?id=1300793 . Thanks for your help.
Based on your feedback, I've filed bugzilla.mozilla.org/show_bug.cgi?id=1300793 . Thanks for your help.
<script> "use strict" function A() {} </script> <script>
function B() {} </script> <script>
window.onload = function() { let a = Reflect.ownKeys(A); let b = Reflect.ownKeys(B); document.getElementById("output").value = (a.includes("arguments") === b.includes("arguments")); } </script>
Mozilla Firefox reports true. Google Chrome and node.js report false. Which one is correct?
I looked through Mozilla's Bugzilla, Google Chrome's Monorail, and the ES7 spec to try figuring this out. The closest I could get was section 9.2.7 of the ES7 spec. [1]
Right now I have an inadvertent mix of strict code / non-strict code in my membrane, and this difference is causing my most recent patch to fail tests in nodejs and Google Chrome, and to pass in Mozilla Firefox. In Chrome and nodejs, I get:
TypeError: 'ownKeys' on proxy: trap result did not include 'arguments'
If it turns out Google & nodejs are correct, this could be an issue going forward: I can't control whether my membrane library's users are running strict mode code or not... likewise, I don't know if my code should be consistently strict mode or consistently non-strict. (I feel that a mix is not good, except for finding bugs like this...)
My apologies for treating this list as a help forum, but I'm just not sure where else to go...
[1] www.ecma-international.org/ecma-262/7.0/#sec