fix: non-directive "use strict" should not enable parsing in strict mode (#11188)

* fix: non-directive "use strict" should not enable parsing in strict mode

* Remove dead code

* Add stricter type annotations

* set oldStrict explicitly to null

* Fix error

* label callback argument

* update comment

* Address feedback

* Remove this.state.octalPosition

* Add additional tests

* Revert "Remove this.state.octalPosition"

This reverts commit bcc78c9530f8c840f85e86053b75efce662f34d1.

* Remove containsOctal

* Report multiple octal literals in single token

* Fix comments

* remove Array.prototype.flat()
This commit is contained in:
Kai Cataldo 2020-03-05 17:34:27 -05:00 committed by GitHub
parent e297e406ce
commit 2057d2b159
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 5300 additions and 123 deletions

View File

@ -55,6 +55,7 @@ export default class ExpressionParser extends LValParser {
+parseBlock: (
allowDirectives?: boolean,
createNewLexicalScope?: boolean,
afterBlockParse?: (hasStrictModeDirective: boolean) => void,
) => N.BlockStatement;
+parseClass: (
node: N.Class,
@ -1877,9 +1878,6 @@ export default class ExpressionParser extends LValParser {
isMethod?: boolean = false,
): void {
const isExpression = allowExpression && !this.match(tt.braceL);
const oldStrict = this.state.strict;
let useStrict = false;
const oldInParameters = this.state.inParameters;
this.state.inParameters = false;
@ -1887,14 +1885,24 @@ export default class ExpressionParser extends LValParser {
node.body = this.parseMaybeAssign();
this.checkParams(node, false, allowExpression, false);
} else {
const oldStrict = this.state.strict;
// Start a new scope with regard to labels
// flag (restore them to their old value afterwards).
const oldLabels = this.state.labels;
this.state.labels = [];
// FunctionBody[Yield, Await]:
// StatementList[?Yield, ?Await, +Return] opt
this.prodParam.enter(this.prodParam.currentFlags() | PARAM_RETURN);
node.body = this.parseBlock(
true,
false,
// Strict mode function checks after we parse the statements in the function body.
(hasStrictModeDirective: boolean) => {
const nonSimple = !this.isSimpleParamList(node.params);
if (!oldStrict || nonSimple) {
useStrict = this.strictDirective(this.state.end);
// If this is a strict mode function, verify that argument names
// are not repeated, and it does not try to bind the words `eval`
// or `arguments`.
if (useStrict && nonSimple) {
// This logic is here to align the error location with the estree plugin
if (hasStrictModeDirective && nonSimple) {
// This logic is here to align the error location with the ESTree plugin.
const errorPos =
// $FlowIgnore
(node.kind === "method" || node.kind === "constructor") &&
@ -1904,29 +1912,18 @@ export default class ExpressionParser extends LValParser {
: node.start;
this.raise(errorPos, Errors.IllegalLanguageModeDirective);
}
}
// Start a new scope with regard to labels
// flag (restore them to their old value afterwards).
const oldLabels = this.state.labels;
this.state.labels = [];
if (useStrict) this.state.strict = true;
const strictModeChanged = !oldStrict && this.state.strict;
// Add the params to varDeclaredNames to ensure that an error is thrown
// if a let/const declaration in the function clashes with one of the params.
this.checkParams(
node,
!oldStrict && !useStrict && !allowExpression && !isMethod && !nonSimple,
!this.state.strict && !allowExpression && !isMethod && !nonSimple,
allowExpression,
!oldStrict && useStrict,
strictModeChanged,
);
// FunctionBody[Yield, Await]:
// StatementList[?Yield, ?Await, +Return] opt
this.prodParam.enter(this.prodParam.currentFlags() | PARAM_RETURN);
node.body = this.parseBlock(true, false);
this.prodParam.exit();
this.state.labels = oldLabels;
}
this.state.inParameters = oldInParameters;
// Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval'
if (this.state.strict && node.id) {
this.checkLVal(
@ -1935,10 +1932,16 @@ export default class ExpressionParser extends LValParser {
undefined,
"function name",
undefined,
!oldStrict && useStrict,
strictModeChanged,
);
}
this.state.strict = oldStrict;
},
);
this.prodParam.exit();
this.state.labels = oldLabels;
}
this.state.inParameters = oldInParameters;
}
isSimpleParamList(

View File

@ -795,13 +795,20 @@ export default class StatementParser extends ExpressionParser {
parseBlock(
allowDirectives?: boolean = false,
createNewLexicalScope?: boolean = true,
afterBlockParse?: (hasStrictModeDirective: boolean) => void,
): N.BlockStatement {
const node = this.startNode();
this.expect(tt.braceL);
if (createNewLexicalScope) {
this.scope.enter(SCOPE_OTHER);
}
this.parseBlockBody(node, allowDirectives, false, tt.braceR);
this.parseBlockBody(
node,
allowDirectives,
false,
tt.braceR,
afterBlockParse,
);
if (createNewLexicalScope) {
this.scope.exit();
}
@ -821,6 +828,7 @@ export default class StatementParser extends ExpressionParser {
allowDirectives: ?boolean,
topLevel: boolean,
end: TokenType,
afterBlockParse?: (hasStrictModeDirective: boolean) => void,
): void {
const body = (node.body = []);
const directives = (node.directives = []);
@ -829,6 +837,7 @@ export default class StatementParser extends ExpressionParser {
allowDirectives ? directives : undefined,
topLevel,
end,
afterBlockParse,
);
}
@ -838,14 +847,16 @@ export default class StatementParser extends ExpressionParser {
directives: ?(N.Directive[]),
topLevel: boolean,
end: TokenType,
afterBlockParse?: (hasStrictModeDirective: boolean) => void,
): void {
const octalPositions = [];
let parsedNonDirective = false;
let oldStrict;
let octalPosition;
let oldStrict = null;
while (!this.eat(end)) {
if (!parsedNonDirective && this.state.containsOctal && !octalPosition) {
octalPosition = this.state.octalPosition;
// Track octal literals that occur before a "use strict" directive.
if (!parsedNonDirective && this.state.octalPositions.length) {
octalPositions.push(...this.state.octalPositions);
}
const stmt = this.parseStatement(null, topLevel);
@ -854,13 +865,9 @@ export default class StatementParser extends ExpressionParser {
const directive = this.stmtToDirective(stmt);
directives.push(directive);
if (oldStrict === undefined && directive.value.value === "use strict") {
if (oldStrict === null && directive.value.value === "use strict") {
oldStrict = this.state.strict;
this.setStrict(true);
if (octalPosition) {
this.raise(octalPosition, Errors.StrictOctalLiteral);
}
}
continue;
@ -870,6 +877,22 @@ export default class StatementParser extends ExpressionParser {
body.push(stmt);
}
// Throw an error for any octal literals found before a
// "use strict" directive. Strict mode will be set at parse
// time for any literals that occur after the directive.
if (this.state.strict && octalPositions.length) {
for (const pos of octalPositions) {
this.raise(pos, Errors.StrictOctalLiteral);
}
}
if (afterBlockParse) {
afterBlockParse.call(
this,
/* hasStrictModeDirective */ oldStrict !== null,
);
}
if (oldStrict === false) {
this.setStrict(false);
}

View File

@ -4,13 +4,11 @@ import { types as tt, type TokenType } from "../tokenizer/types";
import Tokenizer from "../tokenizer";
import State from "../tokenizer/state";
import type { Node } from "../types";
import { lineBreak, skipWhiteSpace } from "../util/whitespace";
import { lineBreak } from "../util/whitespace";
import { isIdentifierChar } from "../util/identifier";
import * as charCodes from "charcodes";
import { Errors } from "./location";
const literal = /^('|")((?:\\?.)*?)\1/;
type TryParse<Node, Error, Thrown, Aborted, FailState> = {
node: Node,
error: Error,
@ -193,29 +191,6 @@ export default class UtilParser extends Tokenizer {
}
}
strictDirective(start: number): boolean {
for (;;) {
// Try to find string literal.
skipWhiteSpace.lastIndex = start;
// $FlowIgnore
start += skipWhiteSpace.exec(this.input)[0].length;
const match = literal.exec(this.input.slice(start));
if (!match) break;
if (match[2] === "use strict") return true;
start += match[0].length;
// Skip semicolon, if any.
skipWhiteSpace.lastIndex = start;
// $FlowIgnore
start += skipWhiteSpace.exec(this.input)[0].length;
if (this.input[start] === ";") {
start++;
}
}
return false;
}
// tryParse will clone parser state.
// It is expensive and should be used with cautions
tryParse<T: Node | $ReadOnlyArray<Node>>(

View File

@ -224,8 +224,7 @@ export default class Tokenizer extends LocationParser {
const curContext = this.curContext();
if (!curContext || !curContext.preserveSpace) this.skipSpace();
this.state.containsOctal = false;
this.state.octalPosition = null;
this.state.octalPositions = [];
this.state.start = this.state.pos;
this.state.startLoc = this.state.curPosition();
if (this.state.pos >= this.length) {
@ -1033,11 +1032,7 @@ export default class Tokenizer extends LocationParser {
this.input.charCodeAt(start) === charCodes.digit0;
if (octal) {
if (this.state.strict) {
this.raise(
start,
// todo: merge with Errors.StrictOctalLiteral
"Legacy octal literals are not allowed in strict mode",
);
this.raise(start, Errors.StrictOctalLiteral);
}
if (/[89]/.test(this.input.slice(start, this.state.pos))) {
octal = false;
@ -1296,11 +1291,11 @@ export default class Tokenizer extends LocationParser {
return null;
} else if (this.state.strict) {
this.raise(codePos, Errors.StrictOctalLiteral);
} else if (!this.state.containsOctal) {
// These properties are only used to throw an error for an octal which occurs
// in a directive which occurs prior to a "use strict" directive.
this.state.containsOctal = true;
this.state.octalPosition = codePos;
} else {
// This property is used to throw an error for
// an octal literal in a directive that occurs prior
// to a "use strict" directive.
this.state.octalPositions.push(codePos);
}
}

View File

@ -141,9 +141,10 @@ export default class State {
// escape sequences must not be interpreted as keywords.
containsEsc: boolean = false;
// TODO
containsOctal: boolean = false;
octalPosition: ?number = null;
// This property is used to throw an error for
// an octal literal in a directive that occurs prior
// to a "use strict" directive.
octalPositions: number[] = [];
// Names of exports store. `default` is stored as a name for both
// `export default foo;` and `export { foo as default };`.

View File

@ -1 +1,118 @@
("not a directive");
("use strict");
"use strict".foo;
"use strict"[foo];
"use strict"`foo`;
"use strict"(foo);
"use strict"
.foo;
"use strict"
[foo];
"use strict"
`foo`;
"use strict"
(foo);
// Should not be a syntax error because should not be parsed in strict mode.
"\5";
function f(){
"use strict".foo;
"\5";
}
function f(){
"use strict"[foo];
"\5";
}
function f(){
"use strict"`foo`;
"\5";
}
function f(){
"use strict"(foo);
"\5";
}
function f(){
"use strict"
.foo;
"\5";
}
function f(){
"use strict"
[foo];
"\5";
}
function f(){
"use strict"
`foo`;
"\5";
}
function f(){
"use strict"
(foo);
"\5";
}
function f(){
foo();
"use strict".bar;
"\5";
}
function f(){
foo();
"use strict"[bar];
"\5";
}
function f(){
foo();
"use strict"`bar`;
"\5";
}
function f(){
foo();
"use strict"(bar);
"\5";
}
function f(){
foo();
"use strict"
.bar;
"\5";
}
function f(){
foo();
"use strict"
[bar];
"\5";
}
function f(){
foo();
"use strict"
`bar`;
"\5";
}
function f(){
foo();
"use strict"
(bar);
"\5";
}
function f(){
05;
"use strict";
}

View File

@ -0,0 +1,32 @@
function a() {
"\5";
"use strict";
}
function b() {
"\4";
"\5";
"use strict";
}
function c() {
"use strict";
"\5";
}
function d() {
"use strict";
"\4";
"\5";
}
function c() {
"use strict";
05;
}
function d() {
"use strict";
04;
05;
}

View File

@ -0,0 +1,3 @@
{
"sourceType": "script"
}

View File

@ -0,0 +1,891 @@
{
"type": "File",
"start": 0,
"end": 268,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 32,
"column": 1
}
},
"errors": [
"SyntaxError: Octal literal in strict mode (2:4)",
"SyntaxError: Octal literal in strict mode (7:4)",
"SyntaxError: Octal literal in strict mode (8:4)",
"SyntaxError: Octal literal in strict mode (14:4)",
"SyntaxError: Octal literal in strict mode (19:4)",
"SyntaxError: Octal literal in strict mode (20:4)",
"SyntaxError: Octal literal in strict mode (25:2)",
"SyntaxError: Octal literal in strict mode (30:2)",
"SyntaxError: Octal literal in strict mode (31:2)"
],
"program": {
"type": "Program",
"start": 0,
"end": 268,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 32,
"column": 1
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "FunctionDeclaration",
"start": 0,
"end": 40,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 4,
"column": 1
}
},
"id": {
"type": "Identifier",
"start": 9,
"end": 10,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 10
},
"identifierName": "a"
},
"name": "a"
},
"generator": false,
"async": false,
"params": [],
"body": {
"type": "BlockStatement",
"start": 13,
"end": 40,
"loc": {
"start": {
"line": 1,
"column": 13
},
"end": {
"line": 4,
"column": 1
}
},
"body": [],
"directives": [
{
"type": "Directive",
"start": 17,
"end": 22,
"loc": {
"start": {
"line": 2,
"column": 2
},
"end": {
"line": 2,
"column": 7
}
},
"value": {
"type": "DirectiveLiteral",
"start": 17,
"end": 21,
"loc": {
"start": {
"line": 2,
"column": 2
},
"end": {
"line": 2,
"column": 6
}
},
"value": "\\5",
"extra": {
"raw": "\"\\5\"",
"rawValue": "\\5"
}
}
},
{
"type": "Directive",
"start": 25,
"end": 38,
"loc": {
"start": {
"line": 3,
"column": 2
},
"end": {
"line": 3,
"column": 15
}
},
"value": {
"type": "DirectiveLiteral",
"start": 25,
"end": 37,
"loc": {
"start": {
"line": 3,
"column": 2
},
"end": {
"line": 3,
"column": 14
}
},
"value": "use strict",
"extra": {
"raw": "\"use strict\"",
"rawValue": "use strict"
}
}
}
]
}
},
{
"type": "FunctionDeclaration",
"start": 42,
"end": 90,
"loc": {
"start": {
"line": 6,
"column": 0
},
"end": {
"line": 10,
"column": 1
}
},
"id": {
"type": "Identifier",
"start": 51,
"end": 52,
"loc": {
"start": {
"line": 6,
"column": 9
},
"end": {
"line": 6,
"column": 10
},
"identifierName": "b"
},
"name": "b"
},
"generator": false,
"async": false,
"params": [],
"body": {
"type": "BlockStatement",
"start": 55,
"end": 90,
"loc": {
"start": {
"line": 6,
"column": 13
},
"end": {
"line": 10,
"column": 1
}
},
"body": [],
"directives": [
{
"type": "Directive",
"start": 59,
"end": 64,
"loc": {
"start": {
"line": 7,
"column": 2
},
"end": {
"line": 7,
"column": 7
}
},
"value": {
"type": "DirectiveLiteral",
"start": 59,
"end": 63,
"loc": {
"start": {
"line": 7,
"column": 2
},
"end": {
"line": 7,
"column": 6
}
},
"value": "\\4",
"extra": {
"raw": "\"\\4\"",
"rawValue": "\\4"
}
}
},
{
"type": "Directive",
"start": 67,
"end": 72,
"loc": {
"start": {
"line": 8,
"column": 2
},
"end": {
"line": 8,
"column": 7
}
},
"value": {
"type": "DirectiveLiteral",
"start": 67,
"end": 71,
"loc": {
"start": {
"line": 8,
"column": 2
},
"end": {
"line": 8,
"column": 6
}
},
"value": "\\5",
"extra": {
"raw": "\"\\5\"",
"rawValue": "\\5"
}
}
},
{
"type": "Directive",
"start": 75,
"end": 88,
"loc": {
"start": {
"line": 9,
"column": 2
},
"end": {
"line": 9,
"column": 15
}
},
"value": {
"type": "DirectiveLiteral",
"start": 75,
"end": 87,
"loc": {
"start": {
"line": 9,
"column": 2
},
"end": {
"line": 9,
"column": 14
}
},
"value": "use strict",
"extra": {
"raw": "\"use strict\"",
"rawValue": "use strict"
}
}
}
]
}
},
{
"type": "FunctionDeclaration",
"start": 92,
"end": 132,
"loc": {
"start": {
"line": 12,
"column": 0
},
"end": {
"line": 15,
"column": 1
}
},
"id": {
"type": "Identifier",
"start": 101,
"end": 102,
"loc": {
"start": {
"line": 12,
"column": 9
},
"end": {
"line": 12,
"column": 10
},
"identifierName": "c"
},
"name": "c"
},
"generator": false,
"async": false,
"params": [],
"body": {
"type": "BlockStatement",
"start": 105,
"end": 132,
"loc": {
"start": {
"line": 12,
"column": 13
},
"end": {
"line": 15,
"column": 1
}
},
"body": [],
"directives": [
{
"type": "Directive",
"start": 109,
"end": 122,
"loc": {
"start": {
"line": 13,
"column": 2
},
"end": {
"line": 13,
"column": 15
}
},
"value": {
"type": "DirectiveLiteral",
"start": 109,
"end": 121,
"loc": {
"start": {
"line": 13,
"column": 2
},
"end": {
"line": 13,
"column": 14
}
},
"value": "use strict",
"extra": {
"raw": "\"use strict\"",
"rawValue": "use strict"
}
}
},
{
"type": "Directive",
"start": 125,
"end": 130,
"loc": {
"start": {
"line": 14,
"column": 2
},
"end": {
"line": 14,
"column": 7
}
},
"value": {
"type": "DirectiveLiteral",
"start": 125,
"end": 129,
"loc": {
"start": {
"line": 14,
"column": 2
},
"end": {
"line": 14,
"column": 6
}
},
"value": "\\5",
"extra": {
"raw": "\"\\5\"",
"rawValue": "\\5"
}
}
}
]
}
},
{
"type": "FunctionDeclaration",
"start": 134,
"end": 182,
"loc": {
"start": {
"line": 17,
"column": 0
},
"end": {
"line": 21,
"column": 1
}
},
"id": {
"type": "Identifier",
"start": 143,
"end": 144,
"loc": {
"start": {
"line": 17,
"column": 9
},
"end": {
"line": 17,
"column": 10
},
"identifierName": "d"
},
"name": "d"
},
"generator": false,
"async": false,
"params": [],
"body": {
"type": "BlockStatement",
"start": 147,
"end": 182,
"loc": {
"start": {
"line": 17,
"column": 13
},
"end": {
"line": 21,
"column": 1
}
},
"body": [],
"directives": [
{
"type": "Directive",
"start": 151,
"end": 164,
"loc": {
"start": {
"line": 18,
"column": 2
},
"end": {
"line": 18,
"column": 15
}
},
"value": {
"type": "DirectiveLiteral",
"start": 151,
"end": 163,
"loc": {
"start": {
"line": 18,
"column": 2
},
"end": {
"line": 18,
"column": 14
}
},
"value": "use strict",
"extra": {
"raw": "\"use strict\"",
"rawValue": "use strict"
}
}
},
{
"type": "Directive",
"start": 167,
"end": 172,
"loc": {
"start": {
"line": 19,
"column": 2
},
"end": {
"line": 19,
"column": 7
}
},
"value": {
"type": "DirectiveLiteral",
"start": 167,
"end": 171,
"loc": {
"start": {
"line": 19,
"column": 2
},
"end": {
"line": 19,
"column": 6
}
},
"value": "\\4",
"extra": {
"raw": "\"\\4\"",
"rawValue": "\\4"
}
}
},
{
"type": "Directive",
"start": 175,
"end": 180,
"loc": {
"start": {
"line": 20,
"column": 2
},
"end": {
"line": 20,
"column": 7
}
},
"value": {
"type": "DirectiveLiteral",
"start": 175,
"end": 179,
"loc": {
"start": {
"line": 20,
"column": 2
},
"end": {
"line": 20,
"column": 6
}
},
"value": "\\5",
"extra": {
"raw": "\"\\5\"",
"rawValue": "\\5"
}
}
}
]
}
},
{
"type": "FunctionDeclaration",
"start": 184,
"end": 222,
"loc": {
"start": {
"line": 23,
"column": 0
},
"end": {
"line": 26,
"column": 1
}
},
"id": {
"type": "Identifier",
"start": 193,
"end": 194,
"loc": {
"start": {
"line": 23,
"column": 9
},
"end": {
"line": 23,
"column": 10
},
"identifierName": "c"
},
"name": "c"
},
"generator": false,
"async": false,
"params": [],
"body": {
"type": "BlockStatement",
"start": 197,
"end": 222,
"loc": {
"start": {
"line": 23,
"column": 13
},
"end": {
"line": 26,
"column": 1
}
},
"body": [
{
"type": "ExpressionStatement",
"start": 217,
"end": 220,
"loc": {
"start": {
"line": 25,
"column": 2
},
"end": {
"line": 25,
"column": 5
}
},
"expression": {
"type": "NumericLiteral",
"start": 217,
"end": 219,
"loc": {
"start": {
"line": 25,
"column": 2
},
"end": {
"line": 25,
"column": 4
}
},
"extra": {
"rawValue": 5,
"raw": "05"
},
"value": 5
}
}
],
"directives": [
{
"type": "Directive",
"start": 201,
"end": 214,
"loc": {
"start": {
"line": 24,
"column": 2
},
"end": {
"line": 24,
"column": 15
}
},
"value": {
"type": "DirectiveLiteral",
"start": 201,
"end": 213,
"loc": {
"start": {
"line": 24,
"column": 2
},
"end": {
"line": 24,
"column": 14
}
},
"value": "use strict",
"extra": {
"raw": "\"use strict\"",
"rawValue": "use strict"
}
}
}
]
}
},
{
"type": "FunctionDeclaration",
"start": 224,
"end": 268,
"loc": {
"start": {
"line": 28,
"column": 0
},
"end": {
"line": 32,
"column": 1
}
},
"id": {
"type": "Identifier",
"start": 233,
"end": 234,
"loc": {
"start": {
"line": 28,
"column": 9
},
"end": {
"line": 28,
"column": 10
},
"identifierName": "d"
},
"name": "d"
},
"generator": false,
"async": false,
"params": [],
"body": {
"type": "BlockStatement",
"start": 237,
"end": 268,
"loc": {
"start": {
"line": 28,
"column": 13
},
"end": {
"line": 32,
"column": 1
}
},
"body": [
{
"type": "ExpressionStatement",
"start": 257,
"end": 260,
"loc": {
"start": {
"line": 30,
"column": 2
},
"end": {
"line": 30,
"column": 5
}
},
"expression": {
"type": "NumericLiteral",
"start": 257,
"end": 259,
"loc": {
"start": {
"line": 30,
"column": 2
},
"end": {
"line": 30,
"column": 4
}
},
"extra": {
"rawValue": 4,
"raw": "04"
},
"value": 4
}
},
{
"type": "ExpressionStatement",
"start": 263,
"end": 266,
"loc": {
"start": {
"line": 31,
"column": 2
},
"end": {
"line": 31,
"column": 5
}
},
"expression": {
"type": "NumericLiteral",
"start": 263,
"end": 265,
"loc": {
"start": {
"line": 31,
"column": 2
},
"end": {
"line": 31,
"column": 4
}
},
"extra": {
"rawValue": 5,
"raw": "05"
},
"value": 5
}
}
],
"directives": [
{
"type": "Directive",
"start": 241,
"end": 254,
"loc": {
"start": {
"line": 29,
"column": 2
},
"end": {
"line": 29,
"column": 15
}
},
"value": {
"type": "DirectiveLiteral",
"start": 241,
"end": 253,
"loc": {
"start": {
"line": 29,
"column": 2
},
"end": {
"line": 29,
"column": 14
}
},
"value": "use strict",
"extra": {
"raw": "\"use strict\"",
"rawValue": "use strict"
}
}
}
]
}
}
],
"directives": []
}
}

View File

@ -0,0 +1,14 @@
"\01 foo \02 bar \03";
"\4";
"\5";
"use strict";
"\4";
"\5";
04;
05;
"\04 foo \05 bar \06";

View File

@ -0,0 +1,365 @@
{
"type": "File",
"start": 0,
"end": 96,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 14,
"column": 22
}
},
"errors": [
"SyntaxError: Octal literal in strict mode (8:2)",
"SyntaxError: Octal literal in strict mode (9:2)",
"SyntaxError: Octal literal in strict mode (11:0)",
"SyntaxError: Octal literal in strict mode (12:0)",
"SyntaxError: Octal literal in strict mode (14:2)",
"SyntaxError: Octal literal in strict mode (14:10)",
"SyntaxError: Octal literal in strict mode (14:18)",
"SyntaxError: Octal literal in strict mode (1:2)",
"SyntaxError: Octal literal in strict mode (1:10)",
"SyntaxError: Octal literal in strict mode (1:18)",
"SyntaxError: Octal literal in strict mode (3:2)",
"SyntaxError: Octal literal in strict mode (4:2)"
],
"program": {
"type": "Program",
"start": 0,
"end": 96,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 14,
"column": 22
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start": 65,
"end": 68,
"loc": {
"start": {
"line": 11,
"column": 0
},
"end": {
"line": 11,
"column": 3
}
},
"expression": {
"type": "NumericLiteral",
"start": 65,
"end": 67,
"loc": {
"start": {
"line": 11,
"column": 0
},
"end": {
"line": 11,
"column": 2
}
},
"extra": {
"rawValue": 4,
"raw": "04"
},
"value": 4
}
},
{
"type": "ExpressionStatement",
"start": 69,
"end": 72,
"loc": {
"start": {
"line": 12,
"column": 0
},
"end": {
"line": 12,
"column": 3
}
},
"expression": {
"type": "NumericLiteral",
"start": 69,
"end": 71,
"loc": {
"start": {
"line": 12,
"column": 0
},
"end": {
"line": 12,
"column": 2
}
},
"extra": {
"rawValue": 5,
"raw": "05"
},
"value": 5
}
},
{
"type": "ExpressionStatement",
"start": 74,
"end": 96,
"loc": {
"start": {
"line": 14,
"column": 0
},
"end": {
"line": 14,
"column": 22
}
},
"expression": {
"type": "StringLiteral",
"start": 74,
"end": 95,
"loc": {
"start": {
"line": 14,
"column": 0
},
"end": {
"line": 14,
"column": 21
}
},
"extra": {
"rawValue": "\u0004 foo \u0005 bar \u0006",
"raw": "\"\\04 foo \\05 bar \\06\""
},
"value": "\u0004 foo \u0005 bar \u0006"
}
}
],
"directives": [
{
"type": "Directive",
"start": 0,
"end": 22,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 22
}
},
"value": {
"type": "DirectiveLiteral",
"start": 0,
"end": 21,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 21
}
},
"value": "\\01 foo \\02 bar \\03",
"extra": {
"raw": "\"\\01 foo \\02 bar \\03\"",
"rawValue": "\\01 foo \\02 bar \\03"
}
}
},
{
"type": "Directive",
"start": 24,
"end": 29,
"loc": {
"start": {
"line": 3,
"column": 0
},
"end": {
"line": 3,
"column": 5
}
},
"value": {
"type": "DirectiveLiteral",
"start": 24,
"end": 28,
"loc": {
"start": {
"line": 3,
"column": 0
},
"end": {
"line": 3,
"column": 4
}
},
"value": "\\4",
"extra": {
"raw": "\"\\4\"",
"rawValue": "\\4"
}
}
},
{
"type": "Directive",
"start": 30,
"end": 35,
"loc": {
"start": {
"line": 4,
"column": 0
},
"end": {
"line": 4,
"column": 5
}
},
"value": {
"type": "DirectiveLiteral",
"start": 30,
"end": 34,
"loc": {
"start": {
"line": 4,
"column": 0
},
"end": {
"line": 4,
"column": 4
}
},
"value": "\\5",
"extra": {
"raw": "\"\\5\"",
"rawValue": "\\5"
}
}
},
{
"type": "Directive",
"start": 37,
"end": 50,
"loc": {
"start": {
"line": 6,
"column": 0
},
"end": {
"line": 6,
"column": 13
}
},
"value": {
"type": "DirectiveLiteral",
"start": 37,
"end": 49,
"loc": {
"start": {
"line": 6,
"column": 0
},
"end": {
"line": 6,
"column": 12
}
},
"value": "use strict",
"extra": {
"raw": "\"use strict\"",
"rawValue": "use strict"
}
}
},
{
"type": "Directive",
"start": 52,
"end": 57,
"loc": {
"start": {
"line": 8,
"column": 0
},
"end": {
"line": 8,
"column": 5
}
},
"value": {
"type": "DirectiveLiteral",
"start": 52,
"end": 56,
"loc": {
"start": {
"line": 8,
"column": 0
},
"end": {
"line": 8,
"column": 4
}
},
"value": "\\4",
"extra": {
"raw": "\"\\4\"",
"rawValue": "\\4"
}
}
},
{
"type": "Directive",
"start": 58,
"end": 63,
"loc": {
"start": {
"line": 9,
"column": 0
},
"end": {
"line": 9,
"column": 5
}
},
"value": {
"type": "DirectiveLiteral",
"start": 58,
"end": 62,
"loc": {
"start": {
"line": 9,
"column": 0
},
"end": {
"line": 9,
"column": 4
}
},
"value": "\\5",
"extra": {
"raw": "\"\\5\"",
"rawValue": "\\5"
}
}
}
]
}
}

View File

@ -13,7 +13,7 @@
}
},
"errors": [
"SyntaxError: Legacy octal literals are not allowed in strict mode (1:0)"
"SyntaxError: Octal literal in strict mode (1:0)"
],
"program": {
"type": "Program",

View File

@ -13,7 +13,6 @@
}
},
"errors": [
"SyntaxError: Octal literal in strict mode (1:35)",
"SyntaxError: Octal literal in strict mode (1:35)"
],
"program": {

View File

@ -13,8 +13,7 @@
}
},
"errors": [
"SyntaxError: Legacy octal literals are not allowed in strict mode (1:33)",
"SyntaxError: Legacy octal literals are not allowed in strict mode (1:33)"
"SyntaxError: Octal literal in strict mode (1:33)"
],
"program": {
"type": "Program",

View File

@ -13,7 +13,7 @@
}
},
"errors": [
"SyntaxError: Legacy octal literals are not allowed in strict mode (1:36)"
"SyntaxError: Octal literal in strict mode (1:36)"
],
"program": {
"type": "Program",

View File

@ -13,7 +13,7 @@
}
},
"errors": [
"SyntaxError: Legacy octal literals are not allowed in strict mode (1:65)"
"SyntaxError: Octal literal in strict mode (1:65)"
],
"program": {
"type": "Program",

View File

@ -13,7 +13,7 @@
}
},
"errors": [
"SyntaxError: Legacy octal literals are not allowed in strict mode (2:10)"
"SyntaxError: Octal literal in strict mode (2:10)"
],
"program": {
"type": "Program",

View File

@ -13,7 +13,7 @@
}
},
"errors": [
"SyntaxError: Legacy octal literals are not allowed in strict mode (2:10)"
"SyntaxError: Octal literal in strict mode (2:10)"
],
"program": {
"type": "Program",

View File

@ -13,7 +13,7 @@
}
},
"errors": [
"SyntaxError: Legacy octal literals are not allowed in strict mode (1:21)"
"SyntaxError: Octal literal in strict mode (1:21)"
],
"program": {
"type": "Program",

View File

@ -13,7 +13,7 @@
}
},
"errors": [
"SyntaxError: Legacy octal literals are not allowed in strict mode (1:21)"
"SyntaxError: Octal literal in strict mode (1:21)"
],
"program": {
"type": "Program",

View File

@ -13,7 +13,6 @@
}
},
"errors": [
"SyntaxError: Octal literal in strict mode (1:35)",
"SyntaxError: Octal literal in strict mode (1:35)"
],
"program": {

View File

@ -13,8 +13,7 @@
}
},
"errors": [
"SyntaxError: Legacy octal literals are not allowed in strict mode (1:33)",
"SyntaxError: Legacy octal literals are not allowed in strict mode (1:33)"
"SyntaxError: Octal literal in strict mode (1:33)"
],
"program": {
"type": "Program",

View File

@ -13,7 +13,7 @@
}
},
"errors": [
"SyntaxError: Legacy octal literals are not allowed in strict mode (1:36)"
"SyntaxError: Octal literal in strict mode (1:36)"
],
"program": {
"type": "Program",