Skip to content

Commit

Permalink
fix(parser): fixes assignment edge cases
Browse files Browse the repository at this point in the history
Meriyah now passes the fuzzer I'm running and destructuring & assignment works as it should.  Time to move on to the next step !
  • Loading branch information
KFlash committed May 15, 2019
1 parent 7805610 commit b2cf29f
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 18 deletions.
26 changes: 9 additions & 17 deletions src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2568,7 +2568,7 @@ export function parsePrimaryExpressionExtended(
if (IsEvalOrArguments) {
if (context & Context.Strict) report(parser, Errors.StrictEvalArguments);
parser.flags |= Flags.SimpleParameterList;
}
} else parser.flags = (parser.flags | Flags.SimpleParameterList) ^ Flags.SimpleParameterList;
if (!assignable) report(parser, Errors.InvalidAssignmentTarget);

return parseArrowFunctionExpression(parser, context, [expr], /* isAsync */ 0);
Expand Down Expand Up @@ -3883,26 +3883,18 @@ export function parseObjectLiteralOrPattern(
: AssignmentKind.Assignable;

if (parser.token === Token.Comma || parser.token === Token.RightBrace) {
if (parser.assignable & AssignmentKind.NotAssignable) destructible |= DestructuringKind.NotDestructible;
if (parser.assignable & AssignmentKind.NotAssignable) {
destructible |= DestructuringKind.NotDestructible;
}
} else if (parser.destructible & DestructuringKind.Required) {
report(parser, Errors.InvalidDestructuringTarget);
} else {
value = parseMemberOrUpdateExpression(parser, context, value, /* assignable */ 0);

destructible =
parser.assignable & AssignmentKind.NotAssignable ? destructible | DestructuringKind.NotDestructible : 0;

const notAssignable = parser.token !== Token.Assign;
destructible = parser.assignable & AssignmentKind.NotAssignable ? DestructuringKind.NotDestructible : 0;

if (parser.token !== Token.Comma && parser.token !== Token.RightBrace) {
if (notAssignable) destructible |= DestructuringKind.NotDestructible;

value = parseAssignmentExpression(
parser,
(context | Context.DisallowInContext) ^ Context.DisallowInContext,
value
);

if (notAssignable) destructible |= DestructuringKind.NotDestructible;
} else if (notAssignable) {
value = parseAssignmentExpression(parser, context, value);
} else if (parser.token !== Token.Assign) {
destructible |=
type || parser.assignable & AssignmentKind.NotAssignable
? DestructuringKind.NotDestructible
Expand Down
24 changes: 23 additions & 1 deletion test/parser/miscellaneous/directives.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,30 @@ describe('Miscellaneous - Directives', () => {
]) {
it(`/* comment in front */ ${arg}`, () => {
t.doesNotThrow(() => {
parseSource(`/* comment in front */ ${arg}`, undefined, Context.OptionsDirectives);
parseSource(`/* comment in front */ ${arg}`, undefined, Context.OptionsDirectives | Context.OptionsRaw);
});
});

it(`/* comment in front */ ${arg}`, () => {
t.doesNotThrow(() => {
parseSource(
`/* comment in front */ ${arg}`,
undefined,
Context.OptionsDirectives | Context.OptionsWebCompat | Context.OptionsRaw
);
});
});
}

for (const arg of ['.foo', '[foo]', '()', '`x`', ' + x', '/f', '/f/g']) {
t.throws(() => {
parseSource(`function f(){ "use strict" \n /* suffix = */ ${arg} ; eval = 1; }`, undefined, Context.Strict);
});
}

for (const arg of ['foo', '++x', '--x', 'function f(){}', '{x}', ';', '25', 'true']) {
t.throws(() => {
parseSource(`function f(){ "use strict" \n ${arg} ; eval = 1; }`, undefined, Context.None);
});
}
});
102 changes: 102 additions & 0 deletions test/parser/statements/if.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,108 @@ describe('Statements - None', () => {
]);

pass('Statements - If (pass)', [
[
'if (yield === void 0) { async = false; }',
Context.OptionsWebCompat,
{
type: 'Program',
sourceType: 'script',
body: [
{
type: 'IfStatement',
test: {
type: 'BinaryExpression',
left: {
type: 'Identifier',
name: 'yield'
},
right: {
type: 'UnaryExpression',
operator: 'void',
argument: {
type: 'Literal',
value: 0
},
prefix: true
},
operator: '==='
},
consequent: {
type: 'BlockStatement',
body: [
{
type: 'ExpressionStatement',
expression: {
type: 'AssignmentExpression',
left: {
type: 'Identifier',
name: 'async'
},
operator: '=',
right: {
type: 'Literal',
value: false
}
}
}
]
},
alternate: null
}
]
}
],
[
'if (await === void 0) { async = false; }',
Context.OptionsWebCompat,
{
type: 'Program',
sourceType: 'script',
body: [
{
type: 'IfStatement',
test: {
type: 'BinaryExpression',
left: {
type: 'Identifier',
name: 'await'
},
right: {
type: 'UnaryExpression',
operator: 'void',
argument: {
type: 'Literal',
value: 0
},
prefix: true
},
operator: '==='
},
consequent: {
type: 'BlockStatement',
body: [
{
type: 'ExpressionStatement',
expression: {
type: 'AssignmentExpression',
left: {
type: 'Identifier',
name: 'async'
},
operator: '=',
right: {
type: 'Literal',
value: false
}
}
}
]
},
alternate: null
}
]
}
],
[
'if (async === void 0) { async = false; }',
Context.OptionsWebCompat,
Expand Down

0 comments on commit b2cf29f

Please sign in to comment.