Add Path#isInStrictMode (#7712)
* Add Path#isInStrictMode * Fix undefined directives * Explicitly return for arrow expressions
This commit is contained in:
parent
6597a472b3
commit
7ae724f553
@ -688,26 +688,9 @@ export default function transformClass(
|
||||
classState.staticPropBody.map(fn => fn(t.cloneNode(classState.classRef))),
|
||||
);
|
||||
|
||||
const strictParent = path.findParent(path => {
|
||||
if (path.isProgram() && path.node.sourceType === "module") {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (path.isClassBody()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!path.isProgram() && !path.isBlockStatement()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return path.node.directives.some(
|
||||
directive => directive.value.value === "use strict",
|
||||
);
|
||||
});
|
||||
|
||||
const isStrict = path.isInStrictMode();
|
||||
let constructorOnly = classState.classId && body.length === 1;
|
||||
if (constructorOnly && !strictParent) {
|
||||
if (constructorOnly && !isStrict) {
|
||||
for (const param of classState.construct.params) {
|
||||
// It's illegal to put a use strict directive into the body of a function
|
||||
// with non-simple parameters for some reason. So, we have to use a strict
|
||||
@ -720,7 +703,7 @@ export default function transformClass(
|
||||
}
|
||||
|
||||
const directives = constructorOnly ? body[0].body.directives : [];
|
||||
if (!strictParent) {
|
||||
if (!isStrict) {
|
||||
directives.push(t.directive(t.directiveLiteral("use strict")));
|
||||
}
|
||||
|
||||
|
||||
@ -439,3 +439,33 @@ export function isConstantExpression() {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export function isInStrictMode() {
|
||||
const start = this.isProgram() ? this : this.parentPath;
|
||||
|
||||
const strictParent = start.find(path => {
|
||||
if (path.isProgram({ sourceType: "module" })) return true;
|
||||
|
||||
if (path.isClass()) return true;
|
||||
|
||||
if (!path.isProgram() && !path.isFunction()) return false;
|
||||
|
||||
if (
|
||||
path.isArrowFunctionExpression() &&
|
||||
!path.get("body").isBlockStatement()
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let { node } = path;
|
||||
if (path.isFunction()) node = node.body;
|
||||
|
||||
for (const directive of node.directives) {
|
||||
if (directive.value.value === "use strict") {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return !!strictParent;
|
||||
}
|
||||
|
||||
103
packages/babel-traverse/test/introspection.js
Normal file
103
packages/babel-traverse/test/introspection.js
Normal file
@ -0,0 +1,103 @@
|
||||
import traverse from "../lib";
|
||||
import { parse } from "babylon";
|
||||
|
||||
function getPath(code, options = { sourceType: "script" }) {
|
||||
const ast = parse(code, options);
|
||||
let path;
|
||||
traverse(ast, {
|
||||
Program: function(_path) {
|
||||
path = _path;
|
||||
_path.stop();
|
||||
},
|
||||
});
|
||||
return path;
|
||||
}
|
||||
|
||||
describe("path/introspection", function() {
|
||||
describe("isInStrictMode", function() {
|
||||
describe("classes", function() {
|
||||
it("returns parent's strictness for class", function() {
|
||||
let program = getPath("class Test extends Super {}");
|
||||
let klass = program.get("body.0");
|
||||
expect(klass.isInStrictMode()).toBeFalsy();
|
||||
|
||||
program = getPath(`"use strict"; class Test extends Super {}`);
|
||||
klass = program.get("body.0");
|
||||
expect(klass.isInStrictMode()).toBeTruthy();
|
||||
});
|
||||
|
||||
it("returns true for class id", function() {
|
||||
const program = getPath("class Test extends Super {}");
|
||||
const id = program.get("body.0.id");
|
||||
expect(id.isInStrictMode()).toBeTruthy();
|
||||
});
|
||||
|
||||
it("returns true for superClass", function() {
|
||||
const program = getPath("class Test extends Super {}");
|
||||
const superClass = program.get("body.0.superClass");
|
||||
expect(superClass.isInStrictMode()).toBeTruthy();
|
||||
});
|
||||
|
||||
it("returns true for method", function() {
|
||||
const program = getPath("class Test { test() {} }");
|
||||
const method = program.get("body.0.body.body.0");
|
||||
expect(method.isInStrictMode()).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe("program", function() {
|
||||
describe("when script", function() {
|
||||
it("returns true when strict", function() {
|
||||
let program = getPath(`test;`);
|
||||
expect(program.isInStrictMode()).toBeFalsy();
|
||||
|
||||
program = getPath(`"use strict";`);
|
||||
expect(program.isInStrictMode()).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe("when module", function() {
|
||||
it("returns true", function() {
|
||||
const program = getPath(`test;`, { sourceType: "module" });
|
||||
expect(program.isInStrictMode()).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("function", function() {
|
||||
it("returns parent's strictness for function", function() {
|
||||
let program = getPath("function test() {}");
|
||||
let fn = program.get("body.0");
|
||||
expect(fn.isInStrictMode()).toBeFalsy();
|
||||
|
||||
program = getPath(`function test() {"use strict";}`);
|
||||
fn = program.get("body.0");
|
||||
expect(fn.isInStrictMode()).toBeFalsy();
|
||||
|
||||
program = getPath(`"use strict"; function test() {}`);
|
||||
fn = program.get("body.0");
|
||||
expect(fn.isInStrictMode()).toBeTruthy();
|
||||
});
|
||||
|
||||
it("returns function's strictness for id", function() {
|
||||
let program = getPath("function test(a) {}");
|
||||
let id = program.get("body.0.id");
|
||||
expect(id.isInStrictMode()).toBeFalsy();
|
||||
|
||||
program = getPath(`function test(a) {"use strict";}`);
|
||||
id = program.get("body.0.id");
|
||||
expect(id.isInStrictMode()).toBeTruthy();
|
||||
});
|
||||
|
||||
it("returns function's strictness for parameters", function() {
|
||||
let program = getPath("function test(a) {}");
|
||||
let param = program.get("body.0.params.0");
|
||||
expect(param.isInStrictMode()).toBeFalsy();
|
||||
|
||||
program = getPath(`function test(a) {"use strict";}`);
|
||||
param = program.get("body.0.params.0");
|
||||
expect(param.isInStrictMode()).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user