Skip to content

Commit

Permalink
fix(parser): Dedupe some logic to reduce branching
Browse files Browse the repository at this point in the history
  • Loading branch information
KFlash committed May 23, 2019
1 parent 1c0c2e8 commit a69476c
Show file tree
Hide file tree
Showing 6 changed files with 526 additions and 44 deletions.
44 changes: 19 additions & 25 deletions src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3228,12 +3228,8 @@ export function parseArrayExpressionOrPattern(
elements
} as any;

if (!skipInitializer) {
if (consumeOpt(parser, context | Context.AllowRegExp, Token.Assign)) {
return parseArrayOrObjectAssignmentPattern(parser, context, destructible, node) as any;
}

if (parser.token & Token.IsAssignOp) report(parser, Errors.InvalidArrayCompoundAssignment);
if (!skipInitializer && parser.token & Token.IsAssignOp) {
return parseArrayOrObjectAssignmentPattern(parser, context, destructible, node) as any;
}

parser.destructible = destructible;
Expand All @@ -3248,7 +3244,6 @@ export function parseArrayExpressionOrPattern(
* @param context Context masks
* @param destructible
* @param node ESTree AST node
* @param skipInitializer
*/

function parseArrayOrObjectAssignmentPattern(
Expand Down Expand Up @@ -3278,11 +3273,17 @@ function parseArrayOrObjectAssignmentPattern(
// DestructuringAssignmentTarget[Yield] :
// LeftHandSideExpression[?Yield]
//

if (parser.token !== Token.Assign) report(parser, Errors.InvalidObjCompoundAssignment);

nextToken(parser, context | Context.AllowRegExp);

if (destructible & DestructuringKind.CannotDestruct) {
report(parser, destructible & DestructuringKind.MustDestruct ? Errors.InvalidLHS : Errors.InvalidLHS);
}

reinterpretToPattern(parser, node);

const { token } = parser;
const right = parseExpression(parser, (context | Context.DisallowIn) ^ Context.DisallowIn, /* assignable */ 1);

Expand All @@ -3305,7 +3306,7 @@ function parseArrayOrObjectAssignmentPattern(
*
* @param parser Parser object
* @param context Context masks
* @param closingToken
* @param closingToken Token
* @param type Binding type
* @param isAsync
*/
Expand All @@ -3323,6 +3324,7 @@ function parseRestOrSpreadElement(

if (parser.token & (Token.Keyword | Token.IsIdentifier)) {
parser.assignable = AssignmentKind.IsAssignable;

destructible |= parser.token === Token.AwaitKeyword ? DestructuringKind.Await : 0;

argument = parsePrimaryExpressionExtended(parser, context, type, /* inNewExpression */ 0, /* assignable */ 1);
Expand Down Expand Up @@ -3977,13 +3979,13 @@ export function parseObjectLiteralOrPattern(
destructible |=
parser.assignable & AssignmentKind.CannotAssign
? DestructuringKind.CannotDestruct
: token === Token.Assign
? 0
: DestructuringKind.AssignableDestruct;
value = parseAssignmentExpression(parser, (context | Context.DisallowIn) ^ Context.DisallowIn, value);
: token !== Token.Assign
? DestructuringKind.AssignableDestruct
: 0;
value = parseAssignmentExpression(parser, context, value);
} else {
destructible |= DestructuringKind.CannotDestruct;
value = parseAssignmentExpression(parser, (context | Context.DisallowIn) ^ Context.DisallowIn, value);
value = parseAssignmentExpression(parser, context, value);
}
} else {
value = parseLeftHandSideExpression(parser, context, /* assignable */ 1);
Expand All @@ -4003,7 +4005,7 @@ export function parseObjectLiteralOrPattern(
const { token } = parser;

if (parser.token !== Token.Comma && parser.token !== Token.RightBrace) {
value = parseAssignmentExpression(parser, (context | Context.DisallowIn) ^ Context.DisallowIn, value);
value = parseAssignmentExpression(parser, context, value);

if (token !== Token.Assign) destructible |= DestructuringKind.CannotDestruct;
}
Expand Down Expand Up @@ -4054,7 +4056,6 @@ export function parseObjectLiteralOrPattern(
state |= PropertyKind.Computed | PropertyKind.Method;
key = parseComputedPropertyName(parser, context);
value = parseMethodDefinition(parser, context, state);
// destructible |= parser.assignable;
} else {
report(parser, Errors.UnexpectedToken, KeywordDescTable[parser.token & Token.Type]);
}
Expand All @@ -4076,28 +4077,21 @@ export function parseObjectLiteralOrPattern(
}

destructible |= parser.destructible;

consumeOpt(parser, context, Token.Comma);
}

consume(parser, context, Token.RightBrace);

if (prototypeCount > 1) destructible |= DestructuringKind.SeenProto;

//destructible |= parser.flags & Flags.Yield ? DestructuringKind.Yield : 0;

const node = {
type: 'ObjectExpression',
properties
} as any;

if (!skipInitializer) {
if (parser.token === Token.Assign) {
nextToken(parser, context | Context.AllowRegExp);
return parseArrayOrObjectAssignmentPattern(parser, context, destructible, node) as any;
}
if (parser.token & Token.IsAssignOp) {
report(parser, Errors.InvalidObjCompoundAssignment);
}
if (!skipInitializer && parser.token & Token.IsAssignOp) {
return parseArrayOrObjectAssignmentPattern(parser, context, destructible, node) as any;
}

parser.destructible = destructible;
Expand Down
171 changes: 161 additions & 10 deletions test/parser/expressions/object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -829,11 +829,12 @@ describe('Expressions - Object', () => {
'key: await /foo/g',
'key: bar/x',
'key: bar, foo: zoo',
'key: bar/x',
'key: bar/x',
'key: bar/x',
'key: bar/x',
'key: bar/x'
'x:y} = { ',
'} = {',
'x = 1} = {',
'x, y = 1, z = 2} = {',
'a: [b = 1, c = 2][1]} = {a:[]',
'a: [b = 1, c = 2].b} = {a:[]'
]) {
it(`({ ${arg} })`, () => {
t.doesNotThrow(() => {
Expand All @@ -843,25 +844,25 @@ describe('Expressions - Object', () => {

it(`({ ${arg} })`, () => {
t.doesNotThrow(() => {
parseSource(`({ ${arg}, })`, undefined, Context.OptionsWebCompat);
parseSource(`({ ${arg} })`, undefined, Context.OptionsWebCompat);
});
});

it(`({ ${arg} })`, () => {
t.doesNotThrow(() => {
parseSource(`({ ${arg}, })`, undefined, Context.None);
parseSource(`({ ${arg} })`, undefined, Context.None);
});
});

it(`({ ${arg} })`, () => {
t.doesNotThrow(() => {
parseSource(`({ ${arg}, })`, undefined, Context.OptionsNext | Context.OptionsWebCompat);
parseSource(`({ ${arg} })`, undefined, Context.OptionsNext | Context.OptionsWebCompat);
});
});

it(`x = { ${arg} }`, () => {
t.doesNotThrow(() => {
parseSource(`x = { ${arg}, }`, undefined, Context.OptionsWebCompat);
parseSource(`x = { ${arg} }`, undefined, Context.OptionsWebCompat);
});
});

Expand All @@ -874,7 +875,7 @@ describe('Expressions - Object', () => {

it(`"use strict"; ({ ${arg} })`, () => {
t.doesNotThrow(() => {
parseSource(`"use strict"; ({ ${arg}, })`, undefined, Context.OptionsNext);
parseSource(`"use strict"; ({ ${arg} })`, undefined, Context.OptionsNext);
});
});
}
Expand Down Expand Up @@ -1243,6 +1244,24 @@ describe('Expressions - Object', () => {
['({set "x"(y){})', Context.None],
['({async 8(){})', Context.None],
['({set 8(y){})', Context.None],
['({,} = {});', Context.None],
['var {,} = {}', Context.None],
['var {x:y+1} = {};', Context.None],
['var {x:y--} = {};', Context.None],
['var y; ({x:y--} = {});', Context.None],
['var y; ({x:y+1} = {});', Context.None],
['function foo() { return {}; }; var {x:foo().x} = {};', Context.None],
['function foo() { return {}; }; ({x:foo()} = {});', Context.None],
['function foo() { return {}; }; let {x:foo()} = {};', Context.None],
['class foo { method() { ({x:super()} = {}); } }', Context.None],
['let [...[a] = []] = [[]];', Context.None],
['let [...{x} = {}] = [{}];', Context.None],
['let a, r1; ({a:(a1 = r1) = 44} = {})', Context.None],
['({a: ({d = 1,c = 1}.c) = 2} = {});', Context.None],
['({a: {d = 1,c = 1}.c = 2} = {});', Context.None],
['for(var [z] = function ([a]) { } in []) {}', Context.None],
['var a = 1; ({x, y = 1, z = 2} = {a = 2});', Context.None],
['var a = 1; ({x, y = {a = 1}} = {});', Context.None],
['({"foo": {1 = 2}});', Context.None],
['({"foo": {x} = [1] = "bar"});', Context.None],
['({"foo": [x] = [1] = "bar"});', Context.None],
Expand Down Expand Up @@ -2063,6 +2082,138 @@ describe('Expressions - Object', () => {
]
}
],
[
'[{x : [{y:{z = 1}}] }] = [{x:[{y:{}}]}];',
Context.None,
{
type: 'Program',
sourceType: 'script',
body: [
{
type: 'ExpressionStatement',
expression: {
type: 'AssignmentExpression',
left: {
type: 'ArrayPattern',
elements: [
{
type: 'ObjectPattern',
properties: [
{
type: 'Property',
key: {
type: 'Identifier',
name: 'x'
},
value: {
type: 'ArrayPattern',
elements: [
{
type: 'ObjectPattern',
properties: [
{
type: 'Property',
key: {
type: 'Identifier',
name: 'y'
},
value: {
type: 'ObjectPattern',
properties: [
{
type: 'Property',
key: {
type: 'Identifier',
name: 'z'
},
value: {
type: 'AssignmentPattern',
left: {
type: 'Identifier',
name: 'z'
},
right: {
type: 'Literal',
value: 1
}
},
kind: 'init',
computed: false,
method: false,
shorthand: true
}
]
},
kind: 'init',
computed: false,
method: false,
shorthand: false
}
]
}
]
},
kind: 'init',
computed: false,
method: false,
shorthand: false
}
]
}
]
},
operator: '=',
right: {
type: 'ArrayExpression',
elements: [
{
type: 'ObjectExpression',
properties: [
{
type: 'Property',
key: {
type: 'Identifier',
name: 'x'
},
value: {
type: 'ArrayExpression',
elements: [
{
type: 'ObjectExpression',
properties: [
{
type: 'Property',
key: {
type: 'Identifier',
name: 'y'
},
value: {
type: 'ObjectExpression',
properties: []
},
kind: 'init',
computed: false,
method: false,
shorthand: false
}
]
}
]
},
kind: 'init',
computed: false,
method: false,
shorthand: false
}
]
}
]
}
}
}
]
}
],
[
'function *f(){ s = {foo: yield /x/} }',
Context.None,
Expand Down

0 comments on commit a69476c

Please sign in to comment.