Bug: Reflect.ownKeys(function() {}) differs in V8 strict mode than other cases

# Alex Vincent (8 years ago)

<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

# Caitlin Potter (8 years ago)

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

# Oriol Bugzilla (8 years ago)

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.

# Mark S. Miller (8 years ago)

Besides those two, the only other reference to AddRestrictedFunctionProperties is < www.ecma-international.org/ecma-262/7.0/#sec-createintrinsics>

step 12:

  1. 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.

# Caitlin Potter (8 years ago)

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.

# Caitlin Potter (8 years ago)

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.

# Alex Vincent (8 years ago)

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?

# Oriol Bugzilla (8 years ago)

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.

# Alex Vincent (8 years ago)

Based on your feedback, I've filed bugzilla.mozilla.org/show_bug.cgi?id=1300793 . Thanks for your help.

# Alex Vincent (8 years ago)

Based on your feedback, I've filed bugzilla.mozilla.org/show_bug.cgi?id=1300793 . Thanks for your help.