Closed Bug 1204024 Opened 9 years ago Closed 8 years ago

Duplicate __proto__ property in destructuring form throws SyntaxError

Categories

(Core :: JavaScript Engine, defect)

defect
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla52
Tracking Status
firefox43 --- affected
firefox52 --- fixed

People

(Reporter: anba, Assigned: anba)

References

Details

(Keywords: dev-doc-complete, Whiteboard: [DocArea=JS])

Attachments

(5 files, 4 obsolete files)

Similar to bug 866624, but this time restricted to the special __proto__ property.

Test case 1 - Destructuring binding pattern:
---
var {__proto__: a, __proto__: b} = {};
---

Test case 2 - Destructuring assignment:
---
({__proto__: a, __proto__: b} = {});
---


Expected: No SyntaxError
Actual: SyntaxError: property name __proto__ appears more than once in object literal


Note: This issue also points out a specification bug, because ES2015 B.3.1 does not specify whether or not the duplicate __proto__ restriction applies to the covered ObjectLiteral or the actual ObjectLiteral production.
Keywords: dev-doc-needed
Whiteboard: [DocArea=JS]
Attached patch bug1204024.part1.patch (obsolete) — Splinter Review
There seem to be many unnecessary PossibleError allocations throughout the whole Parser (in expr(), assignExpr(), unaryOpExpr(), memberExpr()). Do you think my removals are correct, or am I missing something here?

And pending errors are also thrown too early, e.g. `({z=1}={}, {w=2}, {e=3})=>{}` should parse, but currently throws a SyntaxError (there are many other examples, I still need to write the tests).
Assignee: nobody → andrebargull
Status: NEW → ASSIGNED
Attachment #8796683 - Flags: feedback?(arai.unmht)
Attached patch bug1204024.part2.patch (obsolete) — Splinter Review
The actual patch is simple. PossibleError can't store message arguments, so I had to a new JSMSG_DUPLICATE_PROTO_PROPERTY error message. The message itself should probably be amended, e.g. "duplicate __proto__ initializer in object literal". WDYT?
Attachment #8796686 - Flags: review?(arai.unmht)
Blocks: 1185106, 1243717
Comment on attachment 8796683 [details] [diff] [review]
bug1204024.part1.patch

Review of attachment 8796683 [details] [diff] [review]:
-----------------------------------------------------------------

Looks good.

::: js/src/frontend/Parser.cpp
@@ +3732,5 @@
>  {
> +    if (hasError()) {
> +        DebugOnly<bool> result = parser_.reportWithOffset(reportKind_, strict_, offset_,
> +                                                          errorNumber_);
> +        MOZ_ASSERT(!result, "PossibleError shouldn't be used for recoverable errors");

Can we just always use ParseError instead of reportKind_?
That way result should always be false.

I don't see any reason to make reportKind_ configurable.
if it's not necessary, can you remove the member and corresponding setPending parameter?

@@ +4946,5 @@
>  Parser<ParseHandler>::expressionStatement(YieldHandling yieldHandling, InvokedPrediction invoked)
>  {
>      tokenStream.ungetToken();
> +    Node pnexpr = expr(InAllowed, yieldHandling, TripledotProhibited,
> +                       nullptr /* possibleError */, invoked);

while you're touching this, can you rewrite to this syntax?
  ..., /* possibleError = */ nullptr, ...

it's used in other places.

@@ +8205,5 @@
>  typename ParseHandler::Node
>  Parser<ParseHandler>::memberExpr(YieldHandling yieldHandling, TripledotHandling tripledotHandling, TokenKind tt,
>                                   bool allowCallSyntax, InvokedPrediction invoked)
>  {
> +    Node pn = memberExpr(yieldHandling, tripledotHandling, nullptr /* possibleError */, tt,

here too,
  /* possibleError = */ nullptr

::: js/src/frontend/Parser.h
@@ +1130,1 @@
>                InvokedPrediction invoked = PredictUninvoked);

default parameter should be better written also in definition, as a comment,
especially if it's nullable:

  Parser<ParseHandler>::expr(InHandling inHandling, YieldHandling yieldHandling,
                             TripledotHandling tripledotHandling,
                             PossibleError* possibleError /* = nullptr */,
                             InvokedPrediction invoked /* = PredictUninvoked */)

| = PredictUninvoked| is omitted in all places tho, it would be nice to add it too.
maybe in followup bug.

@@ +1133,1 @@
>                      InvokedPrediction invoked = PredictUninvoked);

same here.

@@ +1146,1 @@
>                     InvokedPrediction invoked = PredictUninvoked);

same here.

@@ +1152,5 @@
>      Node primaryExpr(YieldHandling yieldHandling, TripledotHandling tripledotHandling,
>                       PossibleError* possibleError, TokenKind tt,
>                       InvokedPrediction invoked = PredictUninvoked);
>      Node exprInParens(InHandling inHandling, YieldHandling yieldHandling,
> +                      TripledotHandling tripledotHandling, PossibleError* possibleError = nullptr);

and here.
Attachment #8796683 - Flags: feedback?(arai.unmht) → feedback+
Attachment #8796686 - Flags: review?(arai.unmht) → review+
Depends on: 1305566
Comment on attachment 8796686 [details] [diff] [review]
bug1204024.part2.patch

Review of attachment 8796686 [details] [diff] [review]:
-----------------------------------------------------------------

please add browser.js and shell.js with empty content, in js/src/tests/ecma_7/Destructuring.
(In reply to Tooru Fujisawa [:arai] from comment #4)
> please add browser.js and shell.js with empty content, in
> js/src/tests/ecma_7/Destructuring.

Yes, I know about this issue. I still need to update the patches for bug 1272784, bug 1306701 and bug 1204024, because they weren't generated with `hg diff --git`. Because when I installed TortioseHg for testing purposed, TortioseHg removed my "[diff] git = true" settings from .hgrc. (Apparently TortioseHg only understands "git = True", but not "git = true"... *sigh*)
I had to completely redo part 1, because some of the changes were counter-productive for the upcoming patches to fix bug 1041341. The old "part 1" is now split into three different patches (part 1-2 & 4). The old "part 2" is now "part 5". And the new "part 3" is a clean-up patch to simplify pending error checks for destructuring patterns and to reduce code duplication. 

Try: https://treeherder.mozilla.org/#/jobs?repo=try&revision=921e413c5b16a228cfaa65a543ee84381261867e&selectedJob=28880368
Don't create a PossibleError instance when we're in a context where destructuring forms cannot appear. This change also allows us to remove the duplicate expr(), assignExpr(), memberExpr(), and exprInParens() methods, which seems like a nice bonus; the primaryExpr() parameters were only reordered to match memberExpr(). And I've made the allowCallSyntax of memberExpr() a default parameter for convenience reasons, but I guess it should actually be an enum parameter (e.g. CallSyntaxHandling) - maybe for a follow-up bug.
Attachment #8796683 - Attachment is obsolete: true
Attachment #8799504 - Flags: review?(arai.unmht)
Attached patch bug1204024-part2.patch (obsolete) — Splinter Review
PossibleError can only be used for non-recoverable errors, therefore ParseReportKind and the boolean strict parameter aren't particularly useful as parameters for setPending(). The Node parameter was added for part 5, and the if-condition in transferErrorTo() for part 4.
Attachment #8799507 - Flags: review?(arai.unmht)
Remove the duplicate code in declarationPattern() with a direct call to destructuringDeclaration() and move all PossibleError checks for destructuring patterns to checkDestructuringPattern to avoid repeating the same steps in multiple places.
Attachment #8799508 - Flags: review?(arai.unmht)
Attached patch bug1204024-part4.patch (obsolete) — Splinter Review
Pending PossibleErrors were reported too early in expr() and objectLiteral() resp. PossibleError objects weren't properly passed along in objectLiteral() and arrayInitializer(). Both issues prevented us from recognizing some destructuring forms.
Attachment #8799509 - Flags: review?(arai.unmht)
No additional changes (except for adding {shell,browser}.js files). Carrying r+ from arai.
Attachment #8796686 - Attachment is obsolete: true
Attachment #8799510 - Flags: review+
Attachment #8799504 - Flags: review?(arai.unmht) → review+
Comment on attachment 8799507 [details] [diff] [review]
bug1204024-part2.patch

Review of attachment 8799507 [details] [diff] [review]:
-----------------------------------------------------------------

::: js/src/frontend/Parser.cpp
@@ +3718,5 @@
>  }
>  
>  template <typename ParseHandler>
>  Parser<ParseHandler>::PossibleError::PossibleError(Parser<ParseHandler>& parser)
> +                                                   : parser_(parser), state_(ErrorState::None)

while you're touching this, can you fix the indent here to follow other places?

  template <typename ParseHandler>
  Parser<ParseHandler>::PossibleError::PossibleError(Parser<ParseHandler>& parser)
    : parser_(parser), state_(ErrorState::None)

@@ +3719,5 @@
>  
>  template <typename ParseHandler>
>  Parser<ParseHandler>::PossibleError::PossibleError(Parser<ParseHandler>& parser)
> +                                                   : parser_(parser), state_(ErrorState::None)
> +{ }

Please remove the space.

  {}

::: js/src/frontend/Parser.h
@@ +721,5 @@
>  template <typename ParseHandler>
>  class Parser final : private JS::AutoGCRooter, public StrictModeGetter
>  {
>    private:
> +    typedef typename ParseHandler::Node Node;

Can you change it to c++11 style while you're touching it?
  using Node = typename ParseHandler::Node;
Attachment #8799507 - Flags: review?(arai.unmht) → review+
Attachment #8799508 - Flags: review?(arai.unmht) → review+
Attachment #8799509 - Flags: review?(arai.unmht) → review+
Updated part 2 per review comments. Carrying r+ from arai.
Attachment #8799507 - Attachment is obsolete: true
Attachment #8800392 - Flags: review+
Updated part 4 to apply cleanly on updated part 2. Carrying r+.
Attachment #8799509 - Attachment is obsolete: true
Attachment #8800393 - Flags: review+
Keywords: checkin-needed
Pushed by cbook@mozilla.com:
https://hg.mozilla.org/integration/mozilla-inbound/rev/fe1135c6ee9d
Part 1: Set possibleError to nullptr in expression-only contexts. r=arai
https://hg.mozilla.org/integration/mozilla-inbound/rev/c13851000ef0
Part 2: Restrict PossibleError to non-recoverable errors, because it's not possible to recover from a pending error. r=arai
https://hg.mozilla.org/integration/mozilla-inbound/rev/5ebb036c18ea
Part 3: Move destructuring error checking for PossibleError to checkDestructuringPattern. r=arai
https://hg.mozilla.org/integration/mozilla-inbound/rev/04339bee7352
Part 4: Delay error reporting for pending errors until the destructuring pattern is completely parsed. r=arai
https://hg.mozilla.org/integration/mozilla-inbound/rev/5f5b906ef8c8
Part 5: Allow duplicate __proto__ properties in object destructuring. r=arai
Keywords: checkin-needed
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: