Merge pull request #6776 from loganfsmyth/more-plugin-options

Hoist more plugin options and default useUnicodeFlag to 'true'.
This commit is contained in:
Logan Smyth 2017-11-09 10:56:15 -08:00 committed by GitHub
commit 617d35245f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 84 additions and 49 deletions

View File

@ -1,7 +1,12 @@
import syntaxObjectRestSpread from "@babel/plugin-syntax-object-rest-spread"; import syntaxObjectRestSpread from "@babel/plugin-syntax-object-rest-spread";
import { types as t } from "@babel/core"; import { types as t } from "@babel/core";
export default function() { export default function(api, opts) {
const { useBuiltIns = false } = opts;
if (typeof useBuiltIns !== "boolean") {
throw new Error(".useBuiltIns must be a boolean, or undefined");
}
function hasRestElement(path) { function hasRestElement(path) {
let foundRestElement = false; let foundRestElement = false;
path.traverse({ path.traverse({
@ -347,14 +352,6 @@ export default function() {
ObjectExpression(path, file) { ObjectExpression(path, file) {
if (!hasSpread(path.node)) return; if (!hasSpread(path.node)) return;
const useBuiltIns = file.opts.useBuiltIns || false;
if (typeof useBuiltIns !== "boolean") {
throw new Error(
"proposal-object-rest-spread currently only accepts a boolean " +
"option for useBuiltIns (defaults to false)",
);
}
const args = []; const args = [];
let props = []; let props = [];

View File

@ -1,4 +1,4 @@
{ {
"plugins": [["proposal-object-rest-spread", { "useBuiltIns": "invalidOption" }]], "plugins": [["proposal-object-rest-spread", { "useBuiltIns": "invalidOption" }]],
"throws": "proposal-object-rest-spread currently only accepts a boolean option for useBuiltIns (defaults to false)" "throws": ".useBuiltIns must be a boolean, or undefined"
} }

View File

@ -43,11 +43,18 @@ To transpile to ES6/ES2015:
```js ```js
require("@babel/core").transform(code, { require("@babel/core").transform(code, {
"plugins": [ "plugins": [
["@babel/proposal-unicode-property-regex", { "useUnicodeFlag": true }] ["@babel/proposal-unicode-property-regex", { "useUnicodeFlag": false }]
] ]
}); });
``` ```
## Options
* `useUnicodeFlag` (defaults to `true`)
When disabled with `false`, the transform will convert unicode regexes to
non-unicode regexes, removing the `u` flag. See https://www.npmjs.com/package/regexpu-core#useunicodeflag-default-false- for more information.
## Author ## Author
| [![twitter/mathias](https://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](https://twitter.com/mathias "Follow @mathias on Twitter") | | [![twitter/mathias](https://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](https://twitter.com/mathias "Follow @mathias on Twitter") |

View File

@ -1,18 +1,22 @@
import rewritePattern from "regexpu-core"; import rewritePattern from "regexpu-core";
import * as regex from "@babel/helper-regex"; import * as regex from "@babel/helper-regex";
export default function() { export default function(api, options) {
const { useUnicodeFlag = true } = options;
if (typeof useUnicodeFlag !== "boolean") {
throw new Error(".useUnicodeFlag must be a boolean, or undefined");
}
return { return {
visitor: { visitor: {
RegExpLiteral(path, state) { RegExpLiteral(path) {
const node = path.node; const node = path.node;
if (!regex.is(node, "u")) { if (!regex.is(node, "u")) {
return; return;
} }
const useUnicodeFlag = state.opts.useUnicodeFlag || false;
node.pattern = rewritePattern(node.pattern, node.flags, { node.pattern = rewritePattern(node.pattern, node.flags, {
unicodePropertyEscape: true, unicodePropertyEscape: true,
useUnicodeFlag: useUnicodeFlag, useUnicodeFlag,
}); });
if (!useUnicodeFlag) { if (!useUnicodeFlag) {
regex.pullFlag(node, "u"); regex.pullFlag(node, "u");

View File

@ -1,5 +1,7 @@
{ {
"plugins": [ "plugins": [
["proposal-unicode-property-regex"] ["proposal-unicode-property-regex", {
"useUnicodeFlag": false
}]
] ]
} }

View File

@ -1,6 +1,5 @@
import type NodePath from "@babel/traverse"; import type NodePath from "@babel/traverse";
import type Scope from "@babel/traverse"; import type Scope from "@babel/traverse";
import type File from "../../../file";
import { visitor as tdzVisitor } from "./tdz"; import { visitor as tdzVisitor } from "./tdz";
import values from "lodash/values"; import values from "lodash/values";
import extend from "lodash/extend"; import extend from "lodash/extend";
@ -8,10 +7,18 @@ import { traverse, template, types as t } from "@babel/core";
const DONE = new WeakSet(); const DONE = new WeakSet();
export default function() { export default function(api, opts) {
const { throwIfClosureRequired = false, tdz: tdzEnabled = false } = opts;
if (typeof throwIfClosureRequired !== "boolean") {
throw new Error(`.throwIfClosureRequired must be a boolean, or undefined`);
}
if (typeof tdzEnabled !== "boolean") {
throw new Error(`.throwIfClosureRequired must be a boolean, or undefined`);
}
return { return {
visitor: { visitor: {
VariableDeclaration(path, file) { VariableDeclaration(path) {
const { node, parent, scope } = path; const { node, parent, scope } = path;
if (!isBlockScoped(node)) return; if (!isBlockScoped(node)) return;
convertBlockScopedToVar(path, null, parent, scope, true); convertBlockScopedToVar(path, null, parent, scope, true);
@ -26,7 +33,7 @@ export default function() {
assign._ignoreBlockScopingTDZ = true; assign._ignoreBlockScopingTDZ = true;
nodes.push(t.expressionStatement(assign)); nodes.push(t.expressionStatement(assign));
} }
decl.init = file.addHelper("temporalUndefined"); decl.init = this.addHelper("temporalUndefined");
} }
node._blockHoist = 2; node._blockHoist = 2;
@ -41,7 +48,7 @@ export default function() {
} }
}, },
Loop(path, file) { Loop(path) {
const { parent, scope } = path; const { parent, scope } = path;
path.ensureBlock(); path.ensureBlock();
const blockScoping = new BlockScoping( const blockScoping = new BlockScoping(
@ -49,32 +56,35 @@ export default function() {
path.get("body"), path.get("body"),
parent, parent,
scope, scope,
file, throwIfClosureRequired,
tdzEnabled,
); );
const replace = blockScoping.run(); const replace = blockScoping.run();
if (replace) path.replaceWith(replace); if (replace) path.replaceWith(replace);
}, },
CatchClause(path, file) { CatchClause(path) {
const { parent, scope } = path; const { parent, scope } = path;
const blockScoping = new BlockScoping( const blockScoping = new BlockScoping(
null, null,
path.get("body"), path.get("body"),
parent, parent,
scope, scope,
file, throwIfClosureRequired,
tdzEnabled,
); );
blockScoping.run(); blockScoping.run();
}, },
"BlockStatement|SwitchStatement|Program"(path, file) { "BlockStatement|SwitchStatement|Program"(path) {
if (!ignoreBlock(path)) { if (!ignoreBlock(path)) {
const blockScoping = new BlockScoping( const blockScoping = new BlockScoping(
null, null,
path, path,
path.parent, path.parent,
path.scope, path.scope,
file, throwIfClosureRequired,
tdzEnabled,
); );
blockScoping.run(); blockScoping.run();
} }
@ -324,11 +334,13 @@ class BlockScoping {
blockPath: NodePath, blockPath: NodePath,
parent: Object, parent: Object,
scope: Scope, scope: Scope,
file: File, throwIfClosureRequired: boolean,
tdzEnabled: boolean,
) { ) {
this.parent = parent; this.parent = parent;
this.scope = scope; this.scope = scope;
this.file = file; this.throwIfClosureRequired = throwIfClosureRequired;
this.tdzEnabled = tdzEnabled;
this.blockPath = blockPath; this.blockPath = blockPath;
this.block = blockPath.node; this.block = blockPath.node;
@ -432,7 +444,7 @@ class BlockScoping {
} }
wrapClosure() { wrapClosure() {
if (this.file.opts.throwIfClosureRequired) { if (this.throwIfClosureRequired) {
throw this.blockPath.buildCodeFrameError( throw this.blockPath.buildCodeFrameError(
"Compiling let/const in this block would add a closure " + "Compiling let/const in this block would add a closure " +
"(throwIfClosureRequired).", "(throwIfClosureRequired).",
@ -662,8 +674,9 @@ class BlockScoping {
const state = { const state = {
letReferences: this.letReferences, letReferences: this.letReferences,
closurify: false, closurify: false,
file: this.file,
loopDepth: 0, loopDepth: 0,
tdzEnabled: this.tdzEnabled,
addHelper: name => this.addHelper(name),
}; };
if (isInLoop(this.blockPath)) { if (isInLoop(this.blockPath)) {

View File

@ -12,8 +12,8 @@ function getTDZStatus(refPath, bindingPath) {
} }
} }
function buildTDZAssert(node, file) { function buildTDZAssert(node, state) {
return t.callExpression(file.addHelper("temporalRef"), [ return t.callExpression(state.addHelper("temporalRef"), [
node, node,
t.stringLiteral(node.name), t.stringLiteral(node.name),
]); ]);
@ -29,7 +29,7 @@ function isReference(node, scope, state) {
export const visitor = { export const visitor = {
ReferencedIdentifier(path, state) { ReferencedIdentifier(path, state) {
if (!this.file.opts.tdz) return; if (!state.tdzEnabled) return;
const { node, parent, scope } = path; const { node, parent, scope } = path;
@ -42,7 +42,7 @@ export const visitor = {
if (status === "inside") return; if (status === "inside") return;
if (status === "maybe") { if (status === "maybe") {
const assert = buildTDZAssert(node, state.file); const assert = buildTDZAssert(node, state);
// add tdzThis to parent variable declarator so it's exploded // add tdzThis to parent variable declarator so it's exploded
bindingPath.parent._tdzThis = true; bindingPath.parent._tdzThis = true;
@ -73,7 +73,7 @@ export const visitor = {
AssignmentExpression: { AssignmentExpression: {
exit(path, state) { exit(path, state) {
if (!this.file.opts.tdz) return; if (!state.tdzEnabled) return;
const { node } = path; const { node } = path;
if (node._ignoreBlockScopingTDZ) return; if (node._ignoreBlockScopingTDZ) return;
@ -85,7 +85,7 @@ export const visitor = {
const id = ids[name]; const id = ids[name];
if (isReference(id, path.scope, state)) { if (isReference(id, path.scope, state)) {
nodes.push(buildTDZAssert(id, state.file)); nodes.push(buildTDZAssert(id, state));
} }
} }

View File

@ -1,6 +1,13 @@
import { types as t } from "@babel/core"; import { types as t } from "@babel/core";
export default function() { export default function(api, options) {
const { loose = false } = options;
if (typeof loose !== "boolean") {
throw new Error(`.loose must be a boolean or undefined`);
}
const arrayOnlySpread = loose;
/** /**
* Test if a VariableDeclaration's declarations contains any Patterns. * Test if a VariableDeclaration's declarations contains any Patterns.
*/ */
@ -43,8 +50,9 @@ export default function() {
this.arrays = {}; this.arrays = {};
this.nodes = opts.nodes || []; this.nodes = opts.nodes || [];
this.scope = opts.scope; this.scope = opts.scope;
this.file = opts.file;
this.kind = opts.kind; this.kind = opts.kind;
this.arrayOnlySpread = opts.arrayOnlySpread;
this.addHelper = opts.addHelper;
} }
buildVariableAssignment(id, init) { buildVariableAssignment(id, init) {
@ -88,7 +96,7 @@ export default function() {
toArray(node, count) { toArray(node, count) {
if ( if (
this.file.opts.loose || this.arrayOnlySpread ||
(t.isIdentifier(node) && this.arrays[node.name]) (t.isIdentifier(node) && this.arrays[node.name])
) { ) {
return node; return node;
@ -164,7 +172,7 @@ export default function() {
// //
const value = t.callExpression( const value = t.callExpression(
this.file.addHelper("objectWithoutProperties"), this.addHelper("objectWithoutProperties"),
[objRef, keys], [objRef, keys],
); );
this.nodes.push(this.buildVariableAssignment(spreadProp.argument, value)); this.nodes.push(this.buildVariableAssignment(spreadProp.argument, value));
@ -189,7 +197,7 @@ export default function() {
if (!pattern.properties.length) { if (!pattern.properties.length) {
this.nodes.push( this.nodes.push(
t.expressionStatement( t.expressionStatement(
t.callExpression(this.file.addHelper("objectDestructuringEmpty"), [ t.callExpression(this.addHelper("objectDestructuringEmpty"), [
objRef, objRef,
]), ]),
), ),
@ -370,7 +378,7 @@ export default function() {
path.insertAfter(t.exportNamedDeclaration(null, specifiers)); path.insertAfter(t.exportNamedDeclaration(null, specifiers));
}, },
ForXStatement(path, file) { ForXStatement(path) {
const { node, scope } = path; const { node, scope } = path;
const left = node.left; const left = node.left;
@ -406,9 +414,10 @@ export default function() {
const destructuring = new DestructuringTransformer({ const destructuring = new DestructuringTransformer({
kind: left.kind, kind: left.kind,
file: file,
scope: scope, scope: scope,
nodes: nodes, nodes: nodes,
arrayOnlySpread,
addHelper: name => this.addHelper(name),
}); });
destructuring.init(pattern, key); destructuring.init(pattern, key);
@ -419,7 +428,7 @@ export default function() {
block.body = nodes.concat(block.body); block.body = nodes.concat(block.body);
}, },
CatchClause({ node, scope }, file) { CatchClause({ node, scope }) {
const pattern = node.param; const pattern = node.param;
if (!t.isPattern(pattern)) return; if (!t.isPattern(pattern)) return;
@ -430,16 +439,17 @@ export default function() {
const destructuring = new DestructuringTransformer({ const destructuring = new DestructuringTransformer({
kind: "let", kind: "let",
file: file,
scope: scope, scope: scope,
nodes: nodes, nodes: nodes,
arrayOnlySpread,
addHelper: name => this.addHelper(name),
}); });
destructuring.init(pattern, ref); destructuring.init(pattern, ref);
node.body.body = nodes.concat(node.body.body); node.body.body = nodes.concat(node.body.body);
}, },
AssignmentExpression(path, file) { AssignmentExpression(path) {
const { node, scope } = path; const { node, scope } = path;
if (!t.isPattern(node.left)) return; if (!t.isPattern(node.left)) return;
@ -447,9 +457,10 @@ export default function() {
const destructuring = new DestructuringTransformer({ const destructuring = new DestructuringTransformer({
operator: node.operator, operator: node.operator,
file: file,
scope: scope, scope: scope,
nodes: nodes, nodes: nodes,
arrayOnlySpread,
addHelper: name => this.addHelper(name),
}); });
let ref; let ref;
@ -479,7 +490,7 @@ export default function() {
path.replaceWithMultiple(nodes); path.replaceWithMultiple(nodes);
}, },
VariableDeclaration(path, file) { VariableDeclaration(path) {
const { node, scope, parent } = path; const { node, scope, parent } = path;
if (t.isForXStatement(parent)) return; if (t.isForXStatement(parent)) return;
if (!parent || !path.container) return; // i don't know why this is necessary - TODO if (!parent || !path.container) return; // i don't know why this is necessary - TODO
@ -500,7 +511,8 @@ export default function() {
nodes: nodes, nodes: nodes,
scope: scope, scope: scope,
kind: node.kind, kind: node.kind,
file: file, arrayOnlySpread,
addHelper: name => this.addHelper(name),
}); });
if (t.isPattern(pattern)) { if (t.isPattern(pattern)) {