Permalink
Browse files

Limit strict mode directive to functions with a simple parameter list

Fix #1677
Closes gh-1680
  • Loading branch information...
ariya committed Dec 18, 2016
1 parent 721a8dd commit 8391d896a5c260191d7885325302a339f3b4e026
Showing with 9,667 additions and 134 deletions.
  1. +1 −1 README.md
  2. +1 −0 src/messages.ts
  3. +27 −0 src/parser.ts
  4. +1 −0 test/fixtures/ES2016/strict-directive/invalid-strict-arrow-expression-array-destructuring.js
  5. +288 −0 test/fixtures/ES2016/strict-directive/invalid-strict-arrow-expression-array-destructuring.tree.json
  6. +1 −0 test/fixtures/ES2016/strict-directive/invalid-strict-arrow-expression-default-value.js
  7. +342 −0 test/fixtures/ES2016/strict-directive/invalid-strict-arrow-expression-default-value.tree.json
  8. +1 −0 test/fixtures/ES2016/strict-directive/invalid-strict-arrow-expression-object-destructuring.js
  9. +364 −0 test/fixtures/ES2016/strict-directive/invalid-strict-arrow-expression-object-destructuring.tree.json
  10. +1 −0 test/fixtures/ES2016/strict-directive/invalid-strict-arrow-expression-rest.js
  11. +305 −0 test/fixtures/ES2016/strict-directive/invalid-strict-arrow-expression-rest.tree.json
  12. +1 −0 test/fixtures/ES2016/strict-directive/invalid-strict-function-declaration-array-destructuring.js
  13. +324 −0 ...ixtures/ES2016/strict-directive/invalid-strict-function-declaration-array-destructuring.tree.json
  14. +1 −0 test/fixtures/ES2016/strict-directive/invalid-strict-function-declaration-default-value.js
  15. +378 −0 test/fixtures/ES2016/strict-directive/invalid-strict-function-declaration-default-value.tree.json
  16. +1 −0 test/fixtures/ES2016/strict-directive/invalid-strict-function-declaration-object-destructuring.js
  17. +493 −0 ...xtures/ES2016/strict-directive/invalid-strict-function-declaration-object-destructuring.tree.json
  18. +1 −0 test/fixtures/ES2016/strict-directive/invalid-strict-function-declaration-rest.js
  19. +341 −0 test/fixtures/ES2016/strict-directive/invalid-strict-function-declaration-rest.tree.json
  20. +1 −0 test/fixtures/ES2016/strict-directive/invalid-strict-function-expression-array-destructuring.js
  21. +342 −0 ...fixtures/ES2016/strict-directive/invalid-strict-function-expression-array-destructuring.tree.json
  22. +1 −0 test/fixtures/ES2016/strict-directive/invalid-strict-function-expression-default-value.js
  23. +396 −0 test/fixtures/ES2016/strict-directive/invalid-strict-function-expression-default-value.tree.json
  24. +1 −0 test/fixtures/ES2016/strict-directive/invalid-strict-function-expression-object-destructuring.js
  25. +511 −0 ...ixtures/ES2016/strict-directive/invalid-strict-function-expression-object-destructuring.tree.json
  26. +1 −0 test/fixtures/ES2016/strict-directive/invalid-strict-function-expression-rest.js
  27. +359 −0 test/fixtures/ES2016/strict-directive/invalid-strict-function-expression-rest.tree.json
  28. +1 −0 test/fixtures/ES2016/strict-directive/invalid-strict-generator-array-destructuring.js
  29. +342 −0 test/fixtures/ES2016/strict-directive/invalid-strict-generator-array-destructuring.tree.json
  30. +1 −0 test/fixtures/ES2016/strict-directive/invalid-strict-generator-default-value.js
  31. +140 −132 ...empty-param.tree.json → ES2016/strict-directive/invalid-strict-generator-default-value.tree.json}
  32. +1 −0 test/fixtures/ES2016/strict-directive/invalid-strict-generator-object-destructuring.js
  33. +511 −0 test/fixtures/ES2016/strict-directive/invalid-strict-generator-object-destructuring.tree.json
  34. +1 −0 test/fixtures/ES2016/strict-directive/invalid-strict-generator-rest.js
  35. +359 −0 test/fixtures/ES2016/strict-directive/invalid-strict-generator-rest.tree.json
  36. +1 −0 test/fixtures/ES2016/strict-directive/invalid-strict-method-array-destructuring.js
  37. +436 −0 test/fixtures/ES2016/strict-directive/invalid-strict-method-array-destructuring.tree.json
  38. +1 −0 test/fixtures/ES2016/strict-directive/invalid-strict-method-default-value.js
  39. +490 −0 test/fixtures/ES2016/strict-directive/invalid-strict-method-default-value.tree.json
  40. +1 −0 test/fixtures/ES2016/strict-directive/invalid-strict-method-object-destructuring.js
  41. +512 −0 test/fixtures/ES2016/strict-directive/invalid-strict-method-object-destructuring.tree.json
  42. +1 −0 test/fixtures/ES2016/strict-directive/invalid-strict-method-rest.js
  43. +453 −0 test/fixtures/ES2016/strict-directive/invalid-strict-method-rest.tree.json
  44. +1 −0 test/fixtures/ES2016/strict-directive/invalid-strict-setter-array-destructuring.js
  45. +473 −0 test/fixtures/ES2016/strict-directive/invalid-strict-setter-array-destructuring.tree.json
  46. +1 −0 test/fixtures/ES2016/strict-directive/invalid-strict-setter-default-value.js
  47. +490 −0 test/fixtures/ES2016/strict-directive/invalid-strict-setter-default-value.tree.json
  48. +1 −0 test/fixtures/ES2016/strict-directive/invalid-strict-setter-object-destructuring.js
  49. +512 −0 test/fixtures/ES2016/strict-directive/invalid-strict-setter-object-destructuring.tree.json
  50. +1 −0 test/fixtures/ES2016/strict-directive/invalid-strict-setter-rest.js
  51. +453 −0 test/fixtures/ES2016/strict-directive/invalid-strict-setter-rest.tree.json
  52. +0 −1 test/fixtures/declaration/function/empty-param.js
View
@@ -16,7 +16,7 @@ with the help of [many contributors](https://github.com/jquery/esprima/contribut
- Sensible [syntax tree format](https://github.com/estree/estree/blob/master/es5.md) as standardized by [ESTree project](https://github.com/estree/estree)
- Experimental support for [JSX](https://facebook.github.io/jsx/), a syntax extension for [React](https://facebook.github.io/react/)
- Optional tracking of syntax node location (index-based and line-column)
-- [Heavily tested](http://esprima.org/test/ci.html) (~1400 [unit tests](https://github.com/jquery/esprima/tree/master/test/fixtures) with [full code coverage](https://codecov.io/github/jquery/esprima))
+- [Heavily tested](http://esprima.org/test/ci.html) (~1500 [unit tests](https://github.com/jquery/esprima/tree/master/test/fixtures) with [full code coverage](https://codecov.io/github/jquery/esprima))
### API
View
@@ -13,6 +13,7 @@ export const Messages = {
IllegalContinue: 'Illegal continue statement',
IllegalExportDeclaration: 'Unexpected token',
IllegalImportDeclaration: 'Unexpected token',
+ IllegalLanguageModeDirective: 'Illegal \'use strict\' directive in function with non-simple parameter list',
IllegalReturn: 'Illegal return statement',
InvalidEscapedReservedWord: 'Keyword must not contain escaped characters',
InvalidHexEscapeSequence: 'Invalid hexadecimal escape sequence',
View
@@ -18,6 +18,7 @@ interface Config {
interface Context {
isModule: boolean;
allowIn: boolean;
+ allowStrictDirective: boolean;
allowYield: boolean;
await: boolean;
firstCoverInitializedNameError: any;
@@ -125,6 +126,7 @@ export class Parser {
isModule: false,
await: false,
allowIn: true,
+ allowStrictDirective: true,
allowYield: true,
firstCoverInitializedNameError: null,
isAssignmentTarget: false,
@@ -725,6 +727,8 @@ export class Parser {
this.context.isBindingElement = false;
const previousStrict = this.context.strict;
+ const previousAllowStrictDirective = this.context.allowStrictDirective;
+ this.context.allowStrictDirective = params.simple;
const body = this.isolateCoverGrammar(this.parseFunctionSourceElements);
if (this.context.strict && params.firstRestricted) {
this.tolerateUnexpectedToken(params.firstRestricted, params.message);
@@ -733,6 +737,7 @@ export class Parser {
this.tolerateUnexpectedToken(params.stricted, params.message);
}
this.context.strict = previousStrict;
+ this.context.allowStrictDirective = previousAllowStrictDirective;
return body;
}
@@ -1560,6 +1565,7 @@ export class Parser {
default:
break;
}
+ options.simple = options.simple && (param instanceof Node.Identifier);
}
reinterpretAsCoverFormalsList(expr) {
@@ -1579,6 +1585,7 @@ export class Parser {
}
options = {
+ simple: true,
paramSet: {}
};
@@ -1616,6 +1623,7 @@ export class Parser {
}
return {
+ simple: options.simple,
params: params,
stricted: options.stricted,
firstRestricted: options.firstRestricted,
@@ -1657,6 +1665,9 @@ export class Parser {
this.context.firstCoverInitializedNameError = null;
const previousStrict = this.context.strict;
+ const previousAllowStrictDirective = this.context.allowStrictDirective;
+ this.context.allowStrictDirective = list.simple;
+
const previousAllowYield = this.context.allowYield;
const previousAwait = this.context.await;
this.context.allowYield = true;
@@ -1678,6 +1689,7 @@ export class Parser {
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;
}
@@ -2769,20 +2781,23 @@ export class Parser {
param = this.parseRestElement(params);
this.validateParam(options, param.argument, param.argument.name);
options.params.push(param);
+ options.simple = false;
return;
}
param = this.parsePatternWithDefault(params);
for (let i = 0; i < params.length; i++) {
this.validateParam(options, params[i], params[i].value);
}
+ options.simple = options.simple && (param instanceof Node.Identifier);
options.params.push(param);
}
parseFormalParameters(firstRestricted?) {
let options;
options = {
+ simple: true,
params: [],
firstRestricted: firstRestricted
};
@@ -2804,6 +2819,7 @@ export class Parser {
this.expect(')');
return {
+ simple: options.simple,
params: options.params,
stricted: options.stricted,
firstRestricted: options.firstRestricted,
@@ -2880,6 +2896,8 @@ export class Parser {
}
const previousStrict = this.context.strict;
+ const previousAllowStrictDirective = this.context.allowStrictDirective;
+ this.context.allowStrictDirective = formalParameters.simple;
const body = this.parseFunctionSourceElements();
if (this.context.strict && firstRestricted) {
this.throwUnexpectedToken(firstRestricted, message);
@@ -2889,6 +2907,7 @@ export class Parser {
}
this.context.strict = previousStrict;
+ this.context.allowStrictDirective = previousAllowStrictDirective;
this.context.await = previousAllowAwait;
this.context.allowYield = previousAllowYield;
@@ -2947,6 +2966,8 @@ export class Parser {
}
const previousStrict = this.context.strict;
+ const previousAllowStrictDirective = this.context.allowStrictDirective;
+ this.context.allowStrictDirective = formalParameters.simple;
const body = this.parseFunctionSourceElements();
if (this.context.strict && firstRestricted) {
this.throwUnexpectedToken(firstRestricted, message);
@@ -2955,6 +2976,7 @@ export class Parser {
this.tolerateUnexpectedToken(stricted, message);
}
this.context.strict = previousStrict;
+ this.context.allowStrictDirective = previousAllowStrictDirective;
this.context.await = previousAllowAwait;
this.context.allowYield = previousAllowYield;
@@ -2997,6 +3019,9 @@ export class Parser {
if (firstRestricted) {
this.tolerateUnexpectedToken(firstRestricted, Messages.StrictOctalLiteral);
}
+ if (!this.context.allowStrictDirective) {
+ this.tolerateUnexpectedToken(token, Messages.IllegalLanguageModeDirective);
+ }
} else {
if (!firstRestricted && token.octal) {
firstRestricted = token;
@@ -3033,6 +3058,7 @@ export class Parser {
const isGenerator = false;
const params = {
+ simple: true,
params: [],
stricted: null,
firstRestricted: null,
@@ -3050,6 +3076,7 @@ export class Parser {
const node = this.createNode();
let options = {
+ simple: true,
params: [],
firstRestricted: null,
paramSet: {}
Oops, something went wrong.

0 comments on commit 8391d89

Please sign in to comment.