: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
this.tolerateError(messages_1.Messages.StrictLHSPostfix);
if (!this.context.isAssignmentTarget) {
this.tolerateError(messages_1.Messages.InvalidLHSInAssignment);
this.context.isAssignmentTarget = false;
this.context.isBindingElement = false;
var operator = this.nextToken().value;
expr = this.finalize(this.startNode(startToken), new Node.UpdateExpression(operator, expr, prefix));
// https://tc39.github.io/ecma262/#sec-unary-operators
Parser.prototype.parseAwaitExpression = function () {
var node = this.createNode();
var argument = this.parseUnaryExpression();
return this.finalize(node, new Node.AwaitExpression(argument));
Parser.prototype.parseUnaryExpression = function () {
if (this.match('+') || this.match('-') || this.match('~') || this.match('!') ||
this.matchKeyword('delete') || this.matchKeyword('void') || this.matchKeyword('typeof')) {
var node = this.startNode(this.lookahead);
var token = this.nextToken();
expr = this.inheritCoverGrammar(this.parseUnaryExpression);
expr = this.finalize(node, new Node.UnaryExpression(token.value, expr));
if (this.context.strict && expr.operator === 'delete' && expr.argument.type === syntax_1.Syntax.Identifier) {
this.tolerateError(messages_1.Messages.StrictDelete);
this.context.isAssignmentTarget = false;
this.context.isBindingElement = false;
else if (this.context.await && this.matchContextualKeyword('await')) {
expr = this.parseAwaitExpression();
expr = this.parseUpdateExpression();
Parser.prototype.parseExponentiationExpression = function () {
var startToken = this.lookahead;
var expr = this.inheritCoverGrammar(this.parseUnaryExpression);
if (expr.type !== syntax_1.Syntax.UnaryExpression && this.match('**')) {
this.context.isAssignmentTarget = false;
this.context.isBindingElement = false;
var right = this.isolateCoverGrammar(this.parseExponentiationExpression);
expr = this.finalize(this.startNode(startToken), new Node.BinaryExpression('**', left, right));
// https://tc39.github.io/ecma262/#sec-exp-operator
// https://tc39.github.io/ecma262/#sec-multiplicative-operators
// https://tc39.github.io/ecma262/#sec-additive-operators
// https://tc39.github.io/ecma262/#sec-bitwise-shift-operators
// https://tc39.github.io/ecma262/#sec-relational-operators
// https://tc39.github.io/ecma262/#sec-equality-operators
// https://tc39.github.io/ecma262/#sec-binary-bitwise-operators
// https://tc39.github.io/ecma262/#sec-binary-logical-operators
Parser.prototype.binaryPrecedence = function (token) {
if (token.type === 7 /* Punctuator */) {
precedence = this.operatorPrecedence[op] || 0;
else if (token.type === 4 /* Keyword */) {
precedence = (op === 'instanceof' || (this.context.allowIn && op === 'in')) ? 7 : 0;
Parser.prototype.parseBinaryExpression = function () {
var startToken = this.lookahead;
var expr = this.inheritCoverGrammar(this.parseExponentiationExpression);
var token = this.lookahead;
var prec = this.binaryPrecedence(token);
this.context.isAssignmentTarget = false;
this.context.isBindingElement = false;
var markers = [startToken, this.lookahead];
var right = this.isolateCoverGrammar(this.parseExponentiationExpression);
var stack = [left, token.value, right];
var precedences = [prec];
prec = this.binaryPrecedence(this.lookahead);
// Reduce: make a binary expression from the three topmost entries.
while ((stack.length > 2) && (prec <= precedences[precedences.length - 1])) {
var operator = stack.pop();
var node = this.startNode(markers[markers.length - 1]);
stack.push(this.finalize(node, new Node.BinaryExpression(operator, left, right)));
stack.push(this.nextToken().value);
markers.push(this.lookahead);
stack.push(this.isolateCoverGrammar(this.parseExponentiationExpression));
// Final reduce to clean-up the stack.
var i = stack.length - 1;
var node = this.startNode(markers.pop());
var operator = stack[i - 1];
expr = this.finalize(node, new Node.BinaryExpression(operator, stack[i - 2], expr));
// https://tc39.github.io/ecma262/#sec-conditional-operator
Parser.prototype.parseConditionalExpression = function () {
var startToken = this.lookahead;
var expr = this.inheritCoverGrammar(this.parseBinaryExpression);
var previousAllowIn = this.context.allowIn;
this.context.allowIn = true;
var consequent = this.isolateCoverGrammar(this.parseAssignmentExpression);
this.context.allowIn = previousAllowIn;
var alternate = this.isolateCoverGrammar(this.parseAssignmentExpression);
expr = this.finalize(this.startNode(startToken), new Node.ConditionalExpression(expr, consequent, alternate));
this.context.isAssignmentTarget = false;
this.context.isBindingElement = false;
// https://tc39.github.io/ecma262/#sec-assignment-operators
Parser.prototype.checkPatternParam = function (options, param) {
case syntax_1.Syntax.Identifier:
this.validateParam(options, param, param.name);
case syntax_1.Syntax.RestElement:
this.checkPatternParam(options, param.argument);
case syntax_1.Syntax.AssignmentPattern:
this.checkPatternParam(options, param.left);
case syntax_1.Syntax.ArrayPattern:
for (var i = 0; i < param.elements.length; i++) {
if (param.elements[i] !== null) {
this.checkPatternParam(options, param.elements[i]);
case syntax_1.Syntax.ObjectPattern:
for (var i = 0; i < param.properties.length; i++) {
this.checkPatternParam(options, param.properties[i].value);
options.simple = options.simple && (param instanceof Node.Identifier);
Parser.prototype.reinterpretAsCoverFormalsList = function (expr) {
case syntax_1.Syntax.Identifier:
case ArrowParameterPlaceHolder:
for (var i = 0; i < params.length; ++i) {
if (param.type === syntax_1.Syntax.AssignmentPattern) {
if (param.right.type === syntax_1.Syntax.YieldExpression) {
if (param.right.argument) {
this.throwUnexpectedToken(this.lookahead);
param.right.type = syntax_1.Syntax.Identifier;
param.right.name = 'yield';
delete param.right.argument;
delete param.right.delegate;
else if (asyncArrow && param.type === syntax_1.Syntax.Identifier && param.name === 'await') {
this.throwUnexpectedToken(this.lookahead);
this.checkPatternParam(options, param);
if (this.context.strict || !this.context.allowYield) {
for (var i = 0; i < params.length; ++i) {
if (param.type === syntax_1.Syntax.YieldExpression) {
this.throwUnexpectedToken(this.lookahead);
if (options.message === messages_1.Messages.StrictParamDupe) {
var token = this.context.strict ? options.stricted : options.firstRestricted;
this.throwUnexpectedToken(token, options.message);
stricted: options.stricted,
firstRestricted: options.firstRestricted,
Parser.prototype.parseAssignmentExpression = function () {
if (!this.context.allowYield && this.matchKeyword('yield')) {
expr = this.parseYieldExpression();
var startToken = this.lookahead;
expr = this.parseConditionalExpression();
if (token.type === 3 /* Identifier */ && (token.lineNumber === this.lookahead.lineNumber) && token.value === 'async') {
if (this.lookahead.type === 3 /* Identifier */ || this.matchKeyword('yield')) {
var arg = this.parsePrimaryExpression();
this.reinterpretExpressionAsPattern(arg);
type: ArrowParameterPlaceHolder,
if (expr.type === ArrowParameterPlaceHolder || this.match('=>')) {
// https://tc39.github.io/ecma262/#sec-arrow-function-definitions
this.context.isAssignmentTarget = false;
this.context.isBindingElement = false;
var isAsync = expr.async;
var list = this.reinterpretAsCoverFormalsList(expr);
if (this.hasLineTerminator) {
this.tolerateUnexpectedToken(this.lookahead);
this.context.firstCoverInitializedNameError = null;
var previousStrict = this.context.strict;
var previousAllowStrictDirective = this.context.allowStrictDirective;
this.context.allowStrictDirective = list.simple;
var previousAllowYield = this.context.allowYield;
var previousAwait = this.context.await;
this.context.allowYield = true;
this.context.await = isAsync;
var node = this.startNode(startToken);
var previousAllowIn = this.context.allowIn;
this.context.allowIn = true;
body = this.parseFunctionSourceElements();
this.context.allowIn = previousAllowIn;
body = this.isolateCoverGrammar(this.parseAssignmentExpression);
var expression = body.type !== syntax_1.Syntax.BlockStatement;
if (this.context.strict && list.firstRestricted) {
this.throwUnexpectedToken(list.firstRestricted, list.message);
if (this.context.strict && list.stricted) {
this.tolerateUnexpectedToken(list.stricted, list.message);
expr = isAsync ? this.finalize(node, new Node.AsyncArrowFunctionExpression(list.params, body, expression)) :
this.finalize(node, new Node.ArrowFunctionExpression(list.params, body, expression));
this.context.strict = previousStrict;
this.context.allowStrictDirective = previousAllowStrictDirective;
this.context.allowYield = previousAllowYield;
this.context.await = previousAwait;
if (this.matchAssign()) {
if (!this.context.isAssignmentTarget) {
this.tolerateError(messages_1.Messages.InvalidLHSInAssignment);
if (this.context.strict && expr.type === syntax_1.Syntax.Identifier) {
if (this.scanner.isRestrictedWord(id.name)) {
this.tolerateUnexpectedToken(token, messages_1.Messages.StrictLHSAssignment);
if (this.scanner.isStrictModeReservedWord(id.name)) {
this.tolerateUnexpectedToken(token, messages_1.Messages.StrictReservedWord);
this.context.isAssignmentTarget = false;
this.context.isBindingElement = false;
this.reinterpretExpressionAsPattern(expr);
token = this.nextToken();
var operator = token.value;
var right = this.isolateCoverGrammar(this.parseAssignmentExpression);
expr = this.finalize(this.startNode(startToken), new Node.AssignmentExpression(operator, expr, right));
this.context.firstCoverInitializedNameError = null;
// https://tc39.github.io/ecma262/#sec-comma-operator
Parser.prototype.parseExpression = function () {
var startToken = this.lookahead;
var expr = this.isolateCoverGrammar(this.parseAssignmentExpression);
while (this.lookahead.type !== 2 /* EOF */) {
expressions.push(this.isolateCoverGrammar(this.parseAssignmentExpression));
expr = this.finalize(this.startNode(startToken), new Node.SequenceExpression(expressions));
// https://tc39.github.io/ecma262/#sec-block
Parser.prototype.parseStatementListItem = function () {
this.context.isAssignmentTarget = true;
this.context.isBindingElement = true;
if (this.lookahead.type === 4 /* Keyword */) {
switch (this.lookahead.value) {
if (!this.context.isModule) {
this.tolerateUnexpectedToken(this.lookahead, messages_1.Messages.IllegalExportDeclaration);
statement = this.parseExportDeclaration();
if (!this.context.isModule) {
this.tolerateUnexpectedToken(this.lookahead, messages_1.Messages.IllegalImportDeclaration);
statement = this.parseImportDeclaration();
statement = this.parseLexicalDeclaration({ inFor: false });
statement = this.parseFunctionDeclaration();
statement = this.parseClassDeclaration();
statement = this.isLexicalDeclaration() ? this.parseLexicalDeclaration({ inFor: false }) : this.parseStatement();
statement = this.parseStatement();
statement = this.parseStatement();
Parser.prototype.parseBlock = function () {
var node = this.createNode();
block.push(this.parseStatementListItem());
return this.finalize(node, new Node.BlockStatement(block));
// https://tc39.github.io/ecma262/#sec-let-and-const-declarations
Parser.prototype.parseLexicalBinding = function (kind, options) {
var node = this.createNode();
var id = this.parsePattern(params, kind);
if (this.context.strict && id.type === syntax_1.Syntax.Identifier) {
if (this.scanner.isRestrictedWord(id.name)) {
this.tolerateError(messages_1.Messages.StrictVarName);
if (!this.matchKeyword('in') && !this.matchContextualKeyword('of')) {
init = this.isolateCoverGrammar(this.parseAssignmentExpression);
this.throwError(messages_1.Messages.DeclarationMissingInitializer, 'const');
else if ((!options.inFor && id.type !== syntax_1.Syntax.Identifier) || this.match('=')) {
init = this.isolateCoverGrammar(this.parseAssignmentExpression);
return this.finalize(node, new Node.VariableDeclarator(id, init));
Parser.prototype.parseBindingList = function (kind, options) {
var list = [this.parseLexicalBinding(kind, options)];
while (this.match(',')) {
list.push(this.parseLexicalBinding(kind, options));
Parser.prototype.isLexicalDeclaration = function () {
var state = this.scanner.saveState();
this.scanner.scanComments();
var next = this.scanner.lex();
this.scanner.restoreState(state);
return (next.type === 3 /* Identifier */) ||
(next.type === 7 /* Punctuator */ && next.value === '[') ||
(next.type === 7 /* Punctuator */ && next.value === '{') ||
(next.type === 4 /* Keyword */ && next.value === 'let') ||
(next.type === 4 /* Keyword */ && next.value === 'yield');
Parser.prototype.parseLexicalDeclaration = function (options) {
var node = this.createNode();
var kind = this.nextToken().value;
assert_1.assert(kind === 'let' || kind === 'const', 'Lexical declaration must be either let or const');
var declarations = this.parseBindingList(kind, options);
return this.finalize(node, new Node.VariableDeclaration(declarations, kind));
// https://tc39.github.io/ecma262/#sec-destructuring-binding-patterns
Parser.prototype.parseBindingRestElement = function (params, kind) {
var node = this.createNode();
var arg = this.parsePattern(params, kind);
return this.finalize(node, new Node.RestElement(arg));
Parser.prototype.parseArrayPattern = function (params, kind) {
var node = this.createNode();
while (!this.match(']')) {
elements.push(this.parseBindingRestElement(params, kind));
elements.push(this.parsePatternWithDefault(params, kind));
return this.finalize(node, new Node.ArrayPattern(elements));
Parser.prototype.parsePropertyPattern = function (params, kind) {
var node = this.createNode();
if (this.lookahead.type === 3 /* Identifier */) {
var keyToken = this.lookahead;
key = this.parseVariableIdentifier();
var init = this.finalize(node, new Node.Identifier(keyToken.value));