more architectural changes
This commit is contained in:
parent
afe5eb118c
commit
a226641631
@ -19,7 +19,8 @@
|
|||||||
"no-loop-func": 0,
|
"no-loop-func": 0,
|
||||||
"no-unreachable": 0,
|
"no-unreachable": 0,
|
||||||
"no-labels": 0,
|
"no-labels": 0,
|
||||||
"no-process-exit": 0
|
"no-process-exit": 0,
|
||||||
|
"camelcase": 0
|
||||||
},
|
},
|
||||||
"env": {
|
"env": {
|
||||||
"node": true
|
"node": true
|
||||||
|
|||||||
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,6 +1,6 @@
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
node_modules
|
node_modules
|
||||||
test/core/tmp
|
test/tmp
|
||||||
*.log
|
*.log
|
||||||
*.cache
|
*.cache
|
||||||
/templates.json
|
/templates.json
|
||||||
|
|||||||
@ -6,7 +6,6 @@ cache:
|
|||||||
|
|
||||||
node_js:
|
node_js:
|
||||||
- iojs
|
- iojs
|
||||||
- "0.8"
|
|
||||||
- "0.10"
|
- "0.10"
|
||||||
- "0.12"
|
- "0.12"
|
||||||
|
|
||||||
|
|||||||
@ -10,6 +10,4 @@ commander.option("-t, --output-type [type]", "Type of output (global|umd|var)",
|
|||||||
commander.usage("[options]");
|
commander.usage("[options]");
|
||||||
commander.parse(process.argv);
|
commander.parse(process.argv);
|
||||||
|
|
||||||
util.ensureTemplates().then(function () {
|
console.log(runtime(commander.whitelist, commander.outputType));
|
||||||
console.log(runtime(commander.whitelist, commander.outputType));
|
|
||||||
});
|
|
||||||
|
|||||||
@ -35,7 +35,7 @@ exports.transform = function (filename, code, opts) {
|
|||||||
opts.ignore = null;
|
opts.ignore = null;
|
||||||
opts.only = null;
|
opts.only = null;
|
||||||
|
|
||||||
var result = babel.__plsDontUseThis(code, opts);
|
var result = babel.transform(code, opts);
|
||||||
result.filename = filename;
|
result.filename = filename;
|
||||||
result.actual = code;
|
result.actual = code;
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
2
packages/babel-cli/test/tmp/bar2.js
Normal file
2
packages/babel-cli/test/tmp/bar2.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
var bar = () => console.log("bar");
|
||||||
|
bar();
|
||||||
5
packages/babel-cli/test/tmp/foo2.js
Normal file
5
packages/babel-cli/test/tmp/foo2.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import "./bar2";
|
||||||
|
import "./not_node_modules";
|
||||||
|
|
||||||
|
var foo = () => console.log("foo");
|
||||||
|
foo();
|
||||||
10
packages/babel-cli/test/tmp/not_node_modules.jsx
Normal file
10
packages/babel-cli/test/tmp/not_node_modules.jsx
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
The purpose of this file is to test that the node_modules check in the require
|
||||||
|
hook doesn't mistakenly exclude something like "not_node_modules". To pass, this
|
||||||
|
file merely needs to be transpiled. The transpiled code won't, and doesn't need
|
||||||
|
to, execute without error. It won't execute because React will be undefined.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
<Some jsx="element" />;
|
||||||
|
}
|
||||||
|
catch (e) {}
|
||||||
@ -4,11 +4,6 @@ import * as babylon from "babylon";
|
|||||||
import * as util from "../util";
|
import * as util from "../util";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
|
|
||||||
var deasync;
|
|
||||||
try {
|
|
||||||
deasync = require("deasync");
|
|
||||||
} catch (err) {}
|
|
||||||
|
|
||||||
export { util, babylon as acorn, transform };
|
export { util, babylon as acorn, transform };
|
||||||
export { pipeline } from "../transformation";
|
export { pipeline } from "../transformation";
|
||||||
export { canCompile } from "../util";
|
export { canCompile } from "../util";
|
||||||
@ -42,32 +37,24 @@ export function transformFile(filename: string, opts?: Object, callback: Functio
|
|||||||
|
|
||||||
opts.filename = filename;
|
opts.filename = filename;
|
||||||
|
|
||||||
return transform(fs.createReadStream(filename), opts);
|
fs.readFile(filename, function (err, code) {
|
||||||
|
if (err) return callback(err);
|
||||||
|
|
||||||
|
var result;
|
||||||
|
|
||||||
|
try {
|
||||||
|
result = transform(code, opts);
|
||||||
|
} catch (err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(null, result);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function __plsDontUseThis(code, opts) {
|
export function transformFileSync(filename: string, opts?: Object = {}) {
|
||||||
if (!deasync) {
|
opts.filename = filename;
|
||||||
throw new Error("Sorry, this API isn't available in the current environment.");
|
return transform(fs.readFileSync(filename, "utf8"), opts);
|
||||||
}
|
|
||||||
|
|
||||||
var done = false;
|
|
||||||
var result, err;
|
|
||||||
|
|
||||||
transform(code, opts).then(function (_result) {
|
|
||||||
result = _result;
|
|
||||||
done = true;
|
|
||||||
}, function (_err) {
|
|
||||||
err = _err;
|
|
||||||
done = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
deasync.loopWhile(() => !done);
|
|
||||||
|
|
||||||
if (err) {
|
|
||||||
throw err;
|
|
||||||
} else {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parse(code, opts = {}) {
|
export function parse(code, opts = {}) {
|
||||||
|
|||||||
@ -57,7 +57,7 @@ var compile = function (filename, opts = {}) {
|
|||||||
optsManager.mergeOptions(transformOpts);
|
optsManager.mergeOptions(transformOpts);
|
||||||
opts = optsManager.init(opts);
|
opts = optsManager.init(opts);
|
||||||
|
|
||||||
var cacheKey = `${filename}:${JSON.stringify(opts)}:${babel.version}`;
|
var cacheKey = `${JSON.stringify(opts)}:${babel.version}`;
|
||||||
|
|
||||||
var env = process.env.BABEL_ENV || process.env.NODE_ENV;
|
var env = process.env.BABEL_ENV || process.env.NODE_ENV;
|
||||||
if (env) cacheKey += `:${env}`;
|
if (env) cacheKey += `:${env}`;
|
||||||
@ -70,8 +70,7 @@ var compile = function (filename, opts = {}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
var file = fs.readFileSync(filename, "utf8");
|
result = babel.transformFileSync(filename, extend(opts, {
|
||||||
result = babel.__plsDontUseThis(file, extend(opts, {
|
|
||||||
sourceMap: "both",
|
sourceMap: "both",
|
||||||
ast: false
|
ast: false
|
||||||
}));
|
}));
|
||||||
|
|||||||
@ -45,9 +45,8 @@ export default function (code, opts = {}) {
|
|||||||
parseOpts.plugins.flow = true;
|
parseOpts.plugins.flow = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return babylon.parse(code, parseOpts).then(function (ast) {
|
var ast = babylon.parse(code, parseOpts);
|
||||||
estraverse.attachComments(ast, comments, tokens);
|
estraverse.attachComments(ast, comments, tokens);
|
||||||
ast = normalizeAst(ast, comments, commentsAndTokens);
|
ast = normalizeAst(ast, comments, commentsAndTokens);
|
||||||
return ast;
|
return ast;
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,7 +12,6 @@ import defaults from "lodash/object/defaults";
|
|||||||
import includes from "lodash/collection/includes";
|
import includes from "lodash/collection/includes";
|
||||||
import traverse from "../../traversal";
|
import traverse from "../../traversal";
|
||||||
import Logger from "./logger";
|
import Logger from "./logger";
|
||||||
import { Promise } from "bluebird";
|
|
||||||
import Plugin from "../plugin";
|
import Plugin from "../plugin";
|
||||||
import parse from "../../helpers/parse";
|
import parse from "../../helpers/parse";
|
||||||
import Hub from "../../traversal/hub";
|
import Hub from "../../traversal/hub";
|
||||||
@ -429,10 +428,9 @@ export default class File {
|
|||||||
parseOpts.sourceType = "module";
|
parseOpts.sourceType = "module";
|
||||||
|
|
||||||
this.log.debug("Parse start");
|
this.log.debug("Parse start");
|
||||||
return parse(code, parseOpts).then((ast) => {
|
var ast = parse(code, parseOpts);
|
||||||
this.log.debug("Parse stop");
|
this.log.debug("Parse stop");
|
||||||
return ast;
|
return ast;
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_addAst(ast) {
|
_addAst(ast) {
|
||||||
@ -467,11 +465,7 @@ export default class File {
|
|||||||
}
|
}
|
||||||
this.call("post");
|
this.call("post");
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return this.generate();
|
||||||
util.ensureTemplates().then(() => {
|
|
||||||
resolve(this.generate());
|
|
||||||
}, reject);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wrap(code, callback) {
|
wrap(code, callback) {
|
||||||
@ -479,7 +473,7 @@ export default class File {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (this.shouldIgnore()) {
|
if (this.shouldIgnore()) {
|
||||||
return Promise.resolve(this.makeResult({ code, ignored: true }));
|
return this.makeResult({ code, ignored: true });
|
||||||
} else {
|
} else {
|
||||||
return callback();
|
return callback();
|
||||||
}
|
}
|
||||||
@ -519,9 +513,8 @@ export default class File {
|
|||||||
|
|
||||||
parseCode() {
|
parseCode() {
|
||||||
this.parseShebang();
|
this.parseShebang();
|
||||||
return this.parse(this.code).then((ast) => {
|
var ast = this.parse(this.code);
|
||||||
this.addAst(ast);
|
this.addAst(ast);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldIgnore() {
|
shouldIgnore() {
|
||||||
@ -567,6 +560,10 @@ export default class File {
|
|||||||
map: map
|
map: map
|
||||||
};
|
};
|
||||||
|
|
||||||
|
result.then = function (callback) {
|
||||||
|
callback(result);
|
||||||
|
};
|
||||||
|
|
||||||
if (this.opts.code) {
|
if (this.opts.code) {
|
||||||
result.code = code;
|
result.code = code;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -97,7 +97,7 @@ export default class OptionManager {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
addIgnoreConfig(loc) {
|
addIgnoreConfig(loc) {
|
||||||
var file = fs.readFileSync(loc, "utf8");
|
var file = fs.readFileSync(loc, "utf8");
|
||||||
var lines = file.split("\n");
|
var lines = file.split("\n");
|
||||||
|
|
||||||
lines = lines.map(function (line) {
|
lines = lines.map(function (line) {
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import PluginManager from "./file/plugin-manager";
|
import PluginManager from "./file/plugin-manager";
|
||||||
import normalizeAst from "../helpers/normalize-ast";
|
import normalizeAst from "../helpers/normalize-ast";
|
||||||
import { Promise } from "bluebird";
|
|
||||||
import Plugin from "./plugin";
|
import Plugin from "./plugin";
|
||||||
import assign from "lodash/object/assign";
|
import assign from "lodash/object/assign";
|
||||||
import object from "../helpers/object";
|
import object from "../helpers/object";
|
||||||
@ -91,20 +90,19 @@ export default class Pipeline {
|
|||||||
var file = new File(opts, this);
|
var file = new File(opts, this);
|
||||||
return file.wrap(code, function () {
|
return file.wrap(code, function () {
|
||||||
file.addCode(code);
|
file.addCode(code);
|
||||||
return file.parseCode(code).then(() => file.transform());
|
file.parseCode(code);
|
||||||
|
return file.transform();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
transformFromAst(ast, code, opts) {
|
transformFromAst(ast, code, opts) {
|
||||||
return new Promise((resolve) => {
|
ast = normalizeAst(ast);
|
||||||
ast = normalizeAst(ast);
|
|
||||||
|
|
||||||
var file = new File(opts, this);
|
var file = new File(opts, this);
|
||||||
resolve(file.wrap(code, function () {
|
return file.wrap(code, function () {
|
||||||
file.addCode(code);
|
file.addCode(code);
|
||||||
file.addAst(ast);
|
file.addAst(ast);
|
||||||
return file.transform();
|
return file.transform();
|
||||||
}));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,6 @@ export default {
|
|||||||
//- builtin-pre
|
//- builtin-pre
|
||||||
strict: require("./other/strict"),
|
strict: require("./other/strict"),
|
||||||
eval: require("babel-plugin-eval"),
|
eval: require("babel-plugin-eval"),
|
||||||
_explode: require("./internal/explode"),
|
|
||||||
_validation: require("./internal/validation"),
|
_validation: require("./internal/validation"),
|
||||||
_hoistDirectives: require("./internal/hoist-directives"),
|
_hoistDirectives: require("./internal/hoist-directives"),
|
||||||
"minification.removeDebugger": require("babel-plugin-remove-debugger"),
|
"minification.removeDebugger": require("babel-plugin-remove-debugger"),
|
||||||
|
|||||||
@ -1,34 +0,0 @@
|
|||||||
import clone from "lodash/lang/clone";
|
|
||||||
import * as t from "../../../types";
|
|
||||||
|
|
||||||
export var metadata = {
|
|
||||||
group: "builtin-pre"
|
|
||||||
};
|
|
||||||
|
|
||||||
function buildClone(bindingKey, refKey, check?) {
|
|
||||||
return function (node) {
|
|
||||||
if (node[bindingKey] === node[refKey] || (check && check(node))) {
|
|
||||||
node[refKey] = t.removeComments(clone(node[refKey]));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildListClone(listKey, bindingKey, refKey) {
|
|
||||||
var clone = buildClone(bindingKey, refKey);
|
|
||||||
|
|
||||||
return function (node) {
|
|
||||||
if (!node[listKey]) return;
|
|
||||||
|
|
||||||
for (var subNode of (node[listKey]: Array)) {
|
|
||||||
clone(subNode);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export var visitor = {
|
|
||||||
Property: buildClone("value", "key", function (node) {
|
|
||||||
return t.isAssignmentPattern(node.value) && node.value.left === node.key;
|
|
||||||
}),
|
|
||||||
ExportDeclaration: buildListClone("specifiers", "local", "exported"),
|
|
||||||
ImportDeclaration: buildListClone("specifiers", "local", "imported")
|
|
||||||
};
|
|
||||||
@ -10,7 +10,6 @@ import contains from "lodash/collection/contains";
|
|||||||
import traverse from "./traversal";
|
import traverse from "./traversal";
|
||||||
import isString from "lodash/lang/isString";
|
import isString from "lodash/lang/isString";
|
||||||
import isRegExp from "lodash/lang/isRegExp";
|
import isRegExp from "lodash/lang/isRegExp";
|
||||||
import { Promise } from "bluebird";
|
|
||||||
import Module from "module";
|
import Module from "module";
|
||||||
import isEmpty from "lodash/lang/isEmpty";
|
import isEmpty from "lodash/lang/isEmpty";
|
||||||
import parse from "./helpers/parse";
|
import parse from "./helpers/parse";
|
||||||
@ -157,8 +156,6 @@ var templateVisitor = {
|
|||||||
//
|
//
|
||||||
|
|
||||||
export function template(name: string, nodes?: Array<Object>, keepExpression?: boolean): Object {
|
export function template(name: string, nodes?: Array<Object>, keepExpression?: boolean): Object {
|
||||||
if (!exports.templates) throw new ReferenceError(`haven't initialised templates yet`);
|
|
||||||
|
|
||||||
var ast = exports.templates[name];
|
var ast = exports.templates[name];
|
||||||
if (!ast) throw new ReferenceError(`unknown template ${name}`);
|
if (!ast) throw new ReferenceError(`unknown template ${name}`);
|
||||||
|
|
||||||
@ -183,11 +180,10 @@ export function template(name: string, nodes?: Array<Object>, keepExpression?: b
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseTemplate(loc: string, code: string): Object {
|
export function parseTemplate(loc: string, code: string): Object {
|
||||||
return parse(code, { filename: loc, looseModules: true }).then(function (ast) {
|
var ast = parse(code, { filename: loc, looseModules: true }).program;
|
||||||
return traverse.removeProperties(ast.program);
|
ast = traverse.removeProperties(ast);
|
||||||
});
|
return ast;
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadTemplates() {
|
function loadTemplates() {
|
||||||
@ -198,37 +194,22 @@ function loadTemplates() {
|
|||||||
throw new ReferenceError(messages.get("missingTemplatesDirectory"));
|
throw new ReferenceError(messages.get("missingTemplatesDirectory"));
|
||||||
}
|
}
|
||||||
|
|
||||||
var promises = [];
|
for (var name of (fs.readdirSync(templatesLoc): Array)) {
|
||||||
|
if (name[0] === ".") return;
|
||||||
|
|
||||||
for (let name of (fs.readdirSync(templatesLoc): Array)) {
|
var key = path.basename(name, path.extname(name));
|
||||||
if (name[0] === ".") continue;
|
var loc = path.join(templatesLoc, name);
|
||||||
|
var code = fs.readFileSync(loc, "utf8");
|
||||||
|
|
||||||
let key = path.basename(name, path.extname(name));
|
templates[key] = parseTemplate(loc, code);
|
||||||
let loc = path.join(templatesLoc, name);
|
|
||||||
let code = fs.readFileSync(loc, "utf8");
|
|
||||||
|
|
||||||
promises.push(parseTemplate(loc, code).then(function (template) {
|
|
||||||
templates[key] = template;
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.all(promises).then(function () {
|
return templates;
|
||||||
return exports.templates = templates;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function ensureTemplates() {
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
if (exports.templates) {
|
|
||||||
resolve(exports.templates);
|
|
||||||
} else {
|
|
||||||
resolve(loadTemplates());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
exports.templates = require("../templates.json");
|
exports.templates = require("../../templates.json");
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.code !== "MODULE_NOT_FOUND") throw err;
|
if (err.code !== "MODULE_NOT_FOUND") throw err;
|
||||||
|
exports.templates = loadTemplates();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,12 +12,7 @@ var _ = require("lodash");
|
|||||||
|
|
||||||
require("../lib/polyfill");
|
require("../lib/polyfill");
|
||||||
|
|
||||||
var doneBeforeEval = false;
|
eval(buildExernalHelpers());
|
||||||
function beforeEval() {
|
|
||||||
if (doneBeforeEval) return;
|
|
||||||
doneBeforeEval = true;
|
|
||||||
eval(buildExernalHelpers());
|
|
||||||
}
|
|
||||||
|
|
||||||
global.assertNoOwnProperties = function (obj) {
|
global.assertNoOwnProperties = function (obj) {
|
||||||
assert.equal(Object.getOwnPropertyNames(obj).length, 0);
|
assert.equal(Object.getOwnPropertyNames(obj).length, 0);
|
||||||
@ -49,7 +44,6 @@ chai.assert.throw = function (fn, msg) {
|
|||||||
|
|
||||||
return chai.assert._throw(fn, msg);
|
return chai.assert._throw(fn, msg);
|
||||||
};
|
};
|
||||||
|
|
||||||
var run = function (task, done) {
|
var run = function (task, done) {
|
||||||
var actual = task.actual;
|
var actual = task.actual;
|
||||||
var expect = task.expect;
|
var expect = task.expect;
|
||||||
@ -74,71 +68,62 @@ var run = function (task, done) {
|
|||||||
helper.esvalid(result.ast.program, result.code, opts.loc);
|
helper.esvalid(result.ast.program, result.code, opts.loc);
|
||||||
};
|
};
|
||||||
|
|
||||||
var promises = [];
|
|
||||||
|
|
||||||
if (execCode) {
|
if (execCode) {
|
||||||
promises.push(transform(execCode, getOpts(exec)).then(function (result) {
|
result = transform(execCode, getOpts(exec));
|
||||||
execCode = result.code;
|
execCode = result.code;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var fakeRequire = function (loc) {
|
var fakeRequire = function (loc) {
|
||||||
if (loc === "../../../src/runtime/polyfills/Number.js") {
|
if (loc === "../../../src/runtime/polyfills/Number.js") {
|
||||||
return Number;
|
return Number;
|
||||||
} else if (loc === "../../../src/runtime/polyfills/Math.js") {
|
} else if (loc === "../../../src/runtime/polyfills/Math.js") {
|
||||||
return Math;
|
return Math;
|
||||||
} else {
|
} else {
|
||||||
return require(path.resolve(exec.loc, "..", loc));
|
return require(path.resolve(exec.loc, "..", loc));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var fn = new Function("require", "exports", execCode);
|
var fn = new Function("require", "done", "exports", execCode);
|
||||||
beforeEval();
|
fn.call(global, fakeRequire, chai.assert, {}, done);
|
||||||
fn.call(global, fakeRequire, {});
|
} catch (err) {
|
||||||
} catch (err) {
|
err.message = exec.loc + ": " + err.message;
|
||||||
err.message = exec.loc + ": " + err.message;
|
err.message += codeFrame(execCode);
|
||||||
err.message += codeFrame(execCode);
|
throw err;
|
||||||
throw err;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
checkAst(result, exec);
|
checkAst(result, exec);
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var actualCode = actual.code;
|
var actualCode = actual.code;
|
||||||
var expectCode = expect.code;
|
var expectCode = expect.code;
|
||||||
if (!execCode || actualCode) {
|
if (!execCode || actualCode) {
|
||||||
promises.push(transform(actualCode, getOpts(actual)).then(function (result) {
|
result = transform(actualCode, getOpts(actual));
|
||||||
actualCode = result.code.trim();
|
actualCode = result.code.trim();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
chai.expect(actualCode).to.be.equal(expectCode, actual.loc + " !== " + expect.loc);
|
chai.expect(actualCode).to.be.equal(expectCode, actual.loc + " !== " + expect.loc);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
//require("fs").writeFileSync(expect.loc, actualCode);
|
//require("fs").writeFileSync(expect.loc, actualCode);
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
|
||||||
checkAst(result, actual);
|
checkAst(result, actual);
|
||||||
|
|
||||||
if (task.sourceMap) {
|
|
||||||
chai.expect(result.map).to.deep.equal(task.sourceMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (task.sourceMappings) {
|
|
||||||
var consumer = new sourceMap.SourceMapConsumer(result.map);
|
|
||||||
|
|
||||||
_.each(task.sourceMappings, function (mapping, i) {
|
|
||||||
var actual = mapping.original;
|
|
||||||
|
|
||||||
var expect = consumer.originalPositionFor(mapping.generated);
|
|
||||||
chai.expect({ line: expect.line, column: expect.column }).to.deep.equal(actual);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Promise.all(promises).then(function () {
|
if (task.sourceMap) {
|
||||||
done()
|
chai.expect(result.map).to.deep.equal(task.sourceMap);
|
||||||
}, done);
|
}
|
||||||
|
|
||||||
|
if (task.sourceMappings) {
|
||||||
|
var consumer = new sourceMap.SourceMapConsumer(result.map);
|
||||||
|
|
||||||
|
_.each(task.sourceMappings, function (mapping, i) {
|
||||||
|
var actual = mapping.original;
|
||||||
|
|
||||||
|
var expect = consumer.originalPositionFor(mapping.generated);
|
||||||
|
chai.expect({ line: expect.line, column: expect.column }).to.deep.equal(actual);
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = function (suiteOpts, taskOpts, dynamicOpts) {
|
module.exports = function (suiteOpts, taskOpts, dynamicOpts) {
|
||||||
@ -155,7 +140,11 @@ module.exports = function (suiteOpts, taskOpts, dynamicOpts) {
|
|||||||
_.each(testSuite.tests, function (task) {
|
_.each(testSuite.tests, function (task) {
|
||||||
if (_.contains(suiteOpts.ignoreTasks, task.title) || _.contains(suiteOpts.ignoreTasks, testSuite.title + "/" + task.title)) return;
|
if (_.contains(suiteOpts.ignoreTasks, task.title) || _.contains(suiteOpts.ignoreTasks, testSuite.title + "/" + task.title)) return;
|
||||||
|
|
||||||
test(task.title, !task.disabled && function (done) {
|
var runTest = function (done) {
|
||||||
|
var runTask = function () {
|
||||||
|
run(task, done);
|
||||||
|
};
|
||||||
|
|
||||||
_.extend(task.options, taskOpts);
|
_.extend(task.options, taskOpts);
|
||||||
if (dynamicOpts) dynamicOpts(task.options, task);
|
if (dynamicOpts) dynamicOpts(task.options, task);
|
||||||
|
|
||||||
@ -165,26 +154,24 @@ module.exports = function (suiteOpts, taskOpts, dynamicOpts) {
|
|||||||
// the options object with useless options
|
// the options object with useless options
|
||||||
delete task.options.throws;
|
delete task.options.throws;
|
||||||
|
|
||||||
return run(task, function (err) {
|
assert.throws(runTask, function (err) {
|
||||||
if (err) {
|
return throwMsg === true || err.message.indexOf(throwMsg) >= 0;
|
||||||
// we just wanted any error message
|
|
||||||
if (throwMsg === true) return done();
|
|
||||||
|
|
||||||
if (err.message.indexOf(throwMsg) >= 0) {
|
|
||||||
// success!
|
|
||||||
done();
|
|
||||||
} else {
|
|
||||||
// didn't include it :(
|
|
||||||
done(new Error("Expected an error message of " + JSON.stringify(throwMsg) + " but got " + JSON.stringify(err.message)));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
done(new Error("Expected an error message but got none"));
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
return run(task, done);
|
runTask();
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
|
var callback;
|
||||||
|
if (task.options.asyncExec) {
|
||||||
|
callback = runTest;
|
||||||
|
} else {
|
||||||
|
callback = function () {
|
||||||
|
return runTest();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
test(task.title, !task.disabled && callback);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -2,5 +2,5 @@
|
|||||||
|
|
||||||
var A = "a";
|
var A = "a";
|
||||||
var o = {
|
var o = {
|
||||||
A: A // comment
|
A // comment
|
||||||
};
|
: A };
|
||||||
|
|||||||
3
packages/babel/test/fixtures/transformation/es6.regex.unicode/options.json
vendored
Normal file
3
packages/babel/test/fixtures/transformation/es6.regex.unicode/options.json
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"noCheckAst": true
|
||||||
|
}
|
||||||
@ -3,9 +3,7 @@
|
|||||||
Object.defineProperty(exports, "__esModule", {
|
Object.defineProperty(exports, "__esModule", {
|
||||||
value: true
|
value: true
|
||||||
});
|
});
|
||||||
function f(a) {
|
|
||||||
|
exports.f = function f(a) {
|
||||||
return !a;
|
return !a;
|
||||||
}
|
};
|
||||||
|
|
||||||
exports.f = f;
|
|
||||||
|
|
||||||
|
|||||||
@ -34,9 +34,7 @@ function* x() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function y() {
|
exports.y = function y() {
|
||||||
return [].concat(babelHelpers.toConsumableArray(x()));
|
return [].concat(babelHelpers.toConsumableArray(x()));
|
||||||
}
|
};
|
||||||
|
|
||||||
exports.y = y;
|
|
||||||
|
|
||||||
|
|||||||
@ -22,11 +22,11 @@ suite("generation", function () {
|
|||||||
_.each(helper.get("generation"), function (testSuite) {
|
_.each(helper.get("generation"), function (testSuite) {
|
||||||
suite("generation/" + testSuite.title, function () {
|
suite("generation/" + testSuite.title, function () {
|
||||||
_.each(testSuite.tests, function (task) {
|
_.each(testSuite.tests, function (task) {
|
||||||
test(task.title, !task.disabled && function (done) {
|
test(task.title, !task.disabled && function () {
|
||||||
var expect = task.expect;
|
var expect = task.expect;
|
||||||
var actual = task.actual;
|
var actual = task.actual;
|
||||||
|
|
||||||
parse(actual.code, {
|
var actualAst = parse(actual.code, {
|
||||||
filename: actual.loc,
|
filename: actual.loc,
|
||||||
nonStandard: true,
|
nonStandard: true,
|
||||||
strictMode: false,
|
strictMode: false,
|
||||||
@ -38,11 +38,10 @@ _.each(helper.get("generation"), function (testSuite) {
|
|||||||
"es7.exportExtensions": true,
|
"es7.exportExtensions": true,
|
||||||
"es7.functionBind": true
|
"es7.functionBind": true
|
||||||
}
|
}
|
||||||
}).then(function (actualAst) {
|
});
|
||||||
var actualCode = generate(actualAst, task.options, actual.code).code;
|
|
||||||
chai.expect(actualCode).to.equal(expect.code, actual.loc + " !== " + expect.loc);
|
var actualCode = generate(actualAst, task.options, actual.code).code;
|
||||||
done();
|
chai.expect(actualCode).to.equal(expect.code, actual.loc + " !== " + expect.loc);
|
||||||
}, done);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -12,27 +12,18 @@ suite("util", function () {
|
|||||||
|
|
||||||
test("templates do not recurse", function () {
|
test("templates do not recurse", function () {
|
||||||
var key = __filename;
|
var key = __filename;
|
||||||
|
var KEY = parse("replacedKey").program.body[0].expression;
|
||||||
|
var VALUE = parse("+KEY").program.body[0].expression;
|
||||||
|
|
||||||
|
util.templates[key] = util.parseTemplate(key, "KEY = VALUE;");
|
||||||
|
var result = util.template(key, { KEY: KEY, VALUE: VALUE });
|
||||||
|
delete util.templates[key];
|
||||||
|
|
||||||
return parse("replacedKey").then(function (result) {
|
assert.strictEqual(
|
||||||
var KEY = result.program.body[0].expression;
|
result.right.argument.name,
|
||||||
|
"KEY",
|
||||||
return parse("+KEY").then(function (result) {
|
"template should not recurse into replaced nodes, replacing KEY inside VALUE"
|
||||||
var VALUE = result.program.body[0].expression;
|
);
|
||||||
|
|
||||||
return util.parseTemplate(key, "KEY = VALUE;").then(function (template) {
|
|
||||||
util.templates[key] = template;
|
|
||||||
var result = util.template(key, { KEY: KEY, VALUE: VALUE });
|
|
||||||
delete util.templates[key];
|
|
||||||
|
|
||||||
assert.strictEqual(
|
|
||||||
result.right.argument.name,
|
|
||||||
"KEY",
|
|
||||||
"template should not recurse into replaced nodes, replacing KEY inside VALUE"
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("canCompile", function () {
|
test("canCompile", function () {
|
||||||
|
|||||||
@ -3,5 +3,13 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
Babylon is a streaming parser for <a href="https://github.com/babel/babel">Babel</a>.
|
Babylon is a JavaScript parser used in <a href="https://github.com/babel/babel">Babel</a>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
## Credits
|
||||||
|
|
||||||
|
Heavily based on [acorn](https://github.com/marijnh/acorn) and [acorn-jsx](https://github.com/RReverser/acorn-jsx).
|
||||||
|
Significant diversions expected to occur in the future such as streaming, EBNF definitions, sweet.js integration,
|
||||||
|
interspacial parsing, comment attachment etc.
|
||||||
|
|||||||
@ -5,8 +5,5 @@
|
|||||||
"homepage": "https://babeljs.io/",
|
"homepage": "https://babeljs.io/",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"repository": "babel/babel",
|
"repository": "babel/babel",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js"
|
||||||
"dependencies": {
|
|
||||||
"bluebird": "^2.9.33"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,10 +16,9 @@
|
|||||||
//
|
//
|
||||||
// [opp]: http://en.wikipedia.org/wiki/Operator-precedence_parser
|
// [opp]: http://en.wikipedia.org/wiki/Operator-precedence_parser
|
||||||
|
|
||||||
import {types as tt} from "./tokentype";
|
import { types as tt } from "./tokentype";
|
||||||
import {Parser} from "./state";
|
import { Parser } from "./state";
|
||||||
import {reservedWords} from "./identifier";
|
import { reservedWords } from "./identifier";
|
||||||
import {has} from "./util";
|
|
||||||
|
|
||||||
const pp = Parser.prototype;
|
const pp = Parser.prototype;
|
||||||
|
|
||||||
@ -29,14 +28,15 @@ const pp = Parser.prototype;
|
|||||||
// strict mode, init properties are also not allowed to be repeated.
|
// strict mode, init properties are also not allowed to be repeated.
|
||||||
|
|
||||||
pp.checkPropClash = function (prop, propHash) {
|
pp.checkPropClash = function (prop, propHash) {
|
||||||
if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand))
|
if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand)) return;
|
||||||
return;
|
|
||||||
let key = prop.key, name;
|
let key = prop.key, name;
|
||||||
switch (key.type) {
|
switch (key.type) {
|
||||||
case "Identifier": name = key.name; break;
|
case "Identifier": name = key.name; break;
|
||||||
case "Literal": name = String(key.value); break;
|
case "Literal": name = String(key.value); break;
|
||||||
default: return;
|
default: return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let kind = prop.kind;
|
let kind = prop.kind;
|
||||||
if (this.options.ecmaVersion >= 6) {
|
if (this.options.ecmaVersion >= 6) {
|
||||||
if (name === "__proto__" && kind === "init") {
|
if (name === "__proto__" && kind === "init") {
|
||||||
@ -45,6 +45,7 @@ pp.checkPropClash = function (prop, propHash) {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let other;
|
let other;
|
||||||
if (propHash[name]) {
|
if (propHash[name]) {
|
||||||
other = propHash[name];
|
other = propHash[name];
|
||||||
@ -196,10 +197,11 @@ pp.parseMaybeUnary = function (refShorthandDefaultPos) {
|
|||||||
this.next();
|
this.next();
|
||||||
node.argument = this.parseMaybeUnary();
|
node.argument = this.parseMaybeUnary();
|
||||||
if (refShorthandDefaultPos && refShorthandDefaultPos.start) this.unexpected(refShorthandDefaultPos.start);
|
if (refShorthandDefaultPos && refShorthandDefaultPos.start) this.unexpected(refShorthandDefaultPos.start);
|
||||||
if (update) this.checkLVal(node.argument);
|
if (update) {
|
||||||
else if (this.strict && node.operator === "delete" &&
|
this.checkLVal(node.argument);
|
||||||
node.argument.type === "Identifier")
|
} else if (this.strict && node.operator === "delete" && node.argument.type === "Identifier") {
|
||||||
this.raise(node.start, "Deleting local variable in strict mode");
|
this.raise(node.start, "Deleting local variable in strict mode");
|
||||||
|
}
|
||||||
return this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression");
|
return this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression");
|
||||||
}
|
}
|
||||||
let startPos = this.start, startLoc = this.startLoc;
|
let startPos = this.start, startLoc = this.startLoc;
|
||||||
@ -666,13 +668,13 @@ pp.parseObjPropValue = function (prop, startPos, startLoc, isGenerator, isAsync,
|
|||||||
(this.strict && (reservedWords.strictBind(prop.key.name) || reservedWords.strict(prop.key.name))) ||
|
(this.strict && (reservedWords.strictBind(prop.key.name) || reservedWords.strict(prop.key.name))) ||
|
||||||
(!this.options.allowReserved && this.isReservedWord(prop.key.name)))
|
(!this.options.allowReserved && this.isReservedWord(prop.key.name)))
|
||||||
this.raise(prop.key.start, "Binding " + prop.key.name);
|
this.raise(prop.key.start, "Binding " + prop.key.name);
|
||||||
prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key);
|
prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key.__clone());
|
||||||
} else if (this.type === tt.eq && refShorthandDefaultPos) {
|
} else if (this.type === tt.eq && refShorthandDefaultPos) {
|
||||||
if (!refShorthandDefaultPos.start)
|
if (!refShorthandDefaultPos.start)
|
||||||
refShorthandDefaultPos.start = this.start;
|
refShorthandDefaultPos.start = this.start;
|
||||||
prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key);
|
prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key.__clone());
|
||||||
} else {
|
} else {
|
||||||
prop.value = prop.key;
|
prop.value = prop.key.__clone();
|
||||||
}
|
}
|
||||||
prop.shorthand = true;
|
prop.shorthand = true;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -1,26 +1,5 @@
|
|||||||
// Acorn is a tiny, fast JavaScript parser written in JavaScript.
|
import { Parser, plugins } from "./state";
|
||||||
//
|
import { getOptions } from "./options";
|
||||||
// Acorn was written by Marijn Haverbeke, Ingvar Stepanyan, and
|
|
||||||
// various contributors and released under an MIT license.
|
|
||||||
//
|
|
||||||
// Git repositories for Acorn are available at
|
|
||||||
//
|
|
||||||
// http://marijnhaverbeke.nl/git/acorn
|
|
||||||
// https://github.com/marijnh/acorn.git
|
|
||||||
//
|
|
||||||
// Please use the [github bug tracker][ghbt] to report issues.
|
|
||||||
//
|
|
||||||
// [ghbt]: https://github.com/marijnh/acorn/issues
|
|
||||||
//
|
|
||||||
// This file defines the main parser interface. The library also comes
|
|
||||||
// with a [error-tolerant parser][dammit] and an
|
|
||||||
// [abstract syntax tree walker][walk], defined in other files.
|
|
||||||
//
|
|
||||||
// [dammit]: acorn_loose.js
|
|
||||||
// [walk]: util/walk.js
|
|
||||||
|
|
||||||
import {Parser, plugins} from "./state";
|
|
||||||
import {getOptions} from "./options";
|
|
||||||
import "./parseutil";
|
import "./parseutil";
|
||||||
import "./statement";
|
import "./statement";
|
||||||
import "./lval";
|
import "./lval";
|
||||||
@ -29,29 +8,22 @@ import "./lookahead";
|
|||||||
import "./tokentype";
|
import "./tokentype";
|
||||||
import "./tokencontext";
|
import "./tokencontext";
|
||||||
|
|
||||||
export {Parser, plugins} from "./state";
|
export { Parser, plugins } from "./state";
|
||||||
export {defaultOptions} from "./options";
|
export { defaultOptions } from "./options";
|
||||||
export {SourceLocation} from "./location";
|
export { SourceLocation } from "./location";
|
||||||
export {getLineInfo} from "./location";
|
export { getLineInfo } from "./location";
|
||||||
export {Node} from "./node";
|
export { Node } from "./node";
|
||||||
export {TokenType, types as tokTypes} from "./tokentype";
|
export { TokenType, types as tokTypes } from "./tokentype";
|
||||||
export {TokContext, types as tokContexts} from "./tokencontext";
|
export { TokContext, types as tokContexts } from "./tokencontext";
|
||||||
export {isIdentifierChar, isIdentifierStart} from "./identifier";
|
export { isIdentifierChar, isIdentifierStart } from "./identifier";
|
||||||
export {Token} from "./tokenize";
|
export { Token } from "./tokenize";
|
||||||
export {isNewLine, lineBreak, lineBreakG} from "./whitespace";
|
export { isNewLine, lineBreak, lineBreakG } from "./whitespace";
|
||||||
|
|
||||||
import flowPlugin from "./plugins/flow";
|
import flowPlugin from "./plugins/flow";
|
||||||
import jsxPlugin from "./plugins/jsx";
|
import jsxPlugin from "./plugins/jsx";
|
||||||
plugins.flow = flowPlugin;
|
plugins.flow = flowPlugin;
|
||||||
plugins.jsx = jsxPlugin;
|
plugins.jsx = jsxPlugin;
|
||||||
|
|
||||||
// The main exported interface (under `self.acorn` when in the
|
|
||||||
// browser) is a `parse` function that takes a code string and
|
|
||||||
// returns an abstract syntax tree as specified by [Mozilla parser
|
|
||||||
// API][api].
|
|
||||||
//
|
|
||||||
// [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API
|
|
||||||
|
|
||||||
export function parse(input, options) {
|
export function parse(input, options) {
|
||||||
return new Parser(getOptions(options), input).parse();
|
return new Parser(getOptions(options), input).parse();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import {Parser} from "./state";
|
import { Parser } from "./state";
|
||||||
import {lineBreakG} from "./whitespace";
|
import { lineBreakG } from "./whitespace";
|
||||||
|
|
||||||
// These are used when `options.locations` is on, for the
|
// These are used when `options.locations` is on, for the
|
||||||
// `startLoc` and `endLoc` properties.
|
// `startLoc` and `endLoc` properties.
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import {Parser} from "./state";
|
import { Parser } from "./state";
|
||||||
|
|
||||||
const pp = Parser.prototype;
|
const pp = Parser.prototype;
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import {types as tt} from "./tokentype";
|
import { types as tt } from "./tokentype";
|
||||||
import {Parser} from "./state";
|
import { Parser } from "./state";
|
||||||
import {reservedWords} from "./identifier";
|
import { reservedWords } from "./identifier";
|
||||||
import {has} from "./util";
|
|
||||||
|
|
||||||
const pp = Parser.prototype;
|
const pp = Parser.prototype;
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import {Parser} from "./state";
|
import { Parser } from "./state";
|
||||||
import {SourceLocation} from "./location";
|
import { SourceLocation } from "./location";
|
||||||
|
|
||||||
// Start an AST node, attaching a start offset.
|
// Start an AST node, attaching a start offset.
|
||||||
|
|
||||||
@ -10,12 +10,26 @@ export class Node {
|
|||||||
this.type = "";
|
this.type = "";
|
||||||
this.start = pos;
|
this.start = pos;
|
||||||
this.end = 0;
|
this.end = 0;
|
||||||
if (parser.options.locations)
|
|
||||||
this.loc = new SourceLocation(parser, loc);
|
if (parser) {
|
||||||
if (parser.options.directSourceFile)
|
if (parser.options.locations) {
|
||||||
this.sourceFile = parser.options.directSourceFile;
|
this.loc = new SourceLocation(parser, loc);
|
||||||
if (parser.options.ranges)
|
}
|
||||||
this.range = [pos, 0];
|
|
||||||
|
if (parser.options.directSourceFile) {
|
||||||
|
this.sourceFile = parser.options.directSourceFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parser.options.ranges) {
|
||||||
|
this.range = [pos, 0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__clone() {
|
||||||
|
var node2 = new Node;
|
||||||
|
for (var key in this) node2[key] = this[key];
|
||||||
|
return node2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import {has} from "./util";
|
import { has } from "./util";
|
||||||
import {SourceLocation} from "./location";
|
import { SourceLocation } from "./location";
|
||||||
|
|
||||||
// A second optional argument can be given to further configure
|
// A second optional argument can be given to further configure
|
||||||
// the parser process. These options are recognized:
|
// the parser process. These options are recognized:
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import {types as tt} from "./tokentype";
|
import { types as tt } from "./tokentype";
|
||||||
import {Parser} from "./state";
|
import { Parser } from "./state";
|
||||||
import {lineBreak} from "./whitespace";
|
import { lineBreak } from "./whitespace";
|
||||||
|
|
||||||
const pp = Parser.prototype;
|
const pp = Parser.prototype;
|
||||||
|
|
||||||
|
|||||||
@ -820,4 +820,4 @@ export default function (instance) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { TokenType, types as tt } from "../../tokentype";
|
|||||||
import { TokContext, types as tc } from "../../tokencontext";
|
import { TokContext, types as tc } from "../../tokencontext";
|
||||||
import { Parser } from "../../state";
|
import { Parser } from "../../state";
|
||||||
import { isIdentifierChar, isIdentifierStart } from "../../identifier";
|
import { isIdentifierChar, isIdentifierStart } from "../../identifier";
|
||||||
import { isNewLine, lineBreak, lineBreakG } from "../../whitespace";
|
import { isNewLine } from "../../whitespace";
|
||||||
|
|
||||||
const HEX_NUMBER = /^[\da-fA-F]+$/;
|
const HEX_NUMBER = /^[\da-fA-F]+$/;
|
||||||
const DECIMAL_NUMBER = /^\d+$/;
|
const DECIMAL_NUMBER = /^\d+$/;
|
||||||
@ -40,37 +40,39 @@ var pp = Parser.prototype;
|
|||||||
pp.jsxReadToken = function() {
|
pp.jsxReadToken = function() {
|
||||||
var out = "", chunkStart = this.pos;
|
var out = "", chunkStart = this.pos;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (this.pos >= this.input.length)
|
if (this.pos >= this.input.length) {
|
||||||
this.raise(this.start, "Unterminated JSX contents");
|
this.raise(this.start, "Unterminated JSX contents");
|
||||||
|
}
|
||||||
|
|
||||||
var ch = this.input.charCodeAt(this.pos);
|
var ch = this.input.charCodeAt(this.pos);
|
||||||
|
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 60: // "<"
|
case 60: // "<"
|
||||||
case 123: // "{"
|
case 123: // "{"
|
||||||
if (this.pos === this.start) {
|
if (this.pos === this.start) {
|
||||||
if (ch === 60 && this.exprAllowed) {
|
if (ch === 60 && this.exprAllowed) {
|
||||||
++this.pos;
|
++this.pos;
|
||||||
return this.finishToken(tt.jsxTagStart);
|
return this.finishToken(tt.jsxTagStart);
|
||||||
|
}
|
||||||
|
return this.getTokenFromCode(ch);
|
||||||
}
|
}
|
||||||
return this.getTokenFromCode(ch);
|
|
||||||
}
|
|
||||||
out += this.input.slice(chunkStart, this.pos);
|
|
||||||
return this.finishToken(tt.jsxText, out);
|
|
||||||
|
|
||||||
case 38: // "&"
|
|
||||||
out += this.input.slice(chunkStart, this.pos);
|
|
||||||
out += this.jsxReadEntity();
|
|
||||||
chunkStart = this.pos;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
if (isNewLine(ch)) {
|
|
||||||
out += this.input.slice(chunkStart, this.pos);
|
out += this.input.slice(chunkStart, this.pos);
|
||||||
out += this.jsxReadNewLine(true);
|
return this.finishToken(tt.jsxText, out);
|
||||||
|
|
||||||
|
case 38: // "&"
|
||||||
|
out += this.input.slice(chunkStart, this.pos);
|
||||||
|
out += this.jsxReadEntity();
|
||||||
chunkStart = this.pos;
|
chunkStart = this.pos;
|
||||||
} else {
|
break;
|
||||||
++this.pos;
|
|
||||||
}
|
default:
|
||||||
|
if (isNewLine(ch)) {
|
||||||
|
out += this.input.slice(chunkStart, this.pos);
|
||||||
|
out += this.jsxReadNewLine(true);
|
||||||
|
chunkStart = this.pos;
|
||||||
|
} else {
|
||||||
|
++this.pos;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -96,8 +98,10 @@ pp.jsxReadNewLine = function(normalizeCRLF) {
|
|||||||
pp.jsxReadString = function(quote) {
|
pp.jsxReadString = function(quote) {
|
||||||
var out = "", chunkStart = ++this.pos;
|
var out = "", chunkStart = ++this.pos;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (this.pos >= this.input.length)
|
if (this.pos >= this.input.length) {
|
||||||
this.raise(this.start, "Unterminated string constant");
|
this.raise(this.start, "Unterminated string constant");
|
||||||
|
}
|
||||||
|
|
||||||
var ch = this.input.charCodeAt(this.pos);
|
var ch = this.input.charCodeAt(this.pos);
|
||||||
if (ch === quote) break;
|
if (ch === quote) break;
|
||||||
if (ch === 38) { // "&"
|
if (ch === 38) { // "&"
|
||||||
@ -119,8 +123,8 @@ pp.jsxReadString = function(quote) {
|
|||||||
pp.jsxReadEntity = function() {
|
pp.jsxReadEntity = function() {
|
||||||
var str = "", count = 0, entity;
|
var str = "", count = 0, entity;
|
||||||
var ch = this.input[this.pos];
|
var ch = this.input[this.pos];
|
||||||
if (ch !== "&")
|
if (ch !== "&") this.raise(this.pos, "Entity must start with an ampersand");
|
||||||
this.raise(this.pos, "Entity must start with an ampersand");
|
|
||||||
var startPos = ++this.pos;
|
var startPos = ++this.pos;
|
||||||
while (this.pos < this.input.length && count++ < 10) {
|
while (this.pos < this.input.length && count++ < 10) {
|
||||||
ch = this.input[this.pos++];
|
ch = this.input[this.pos++];
|
||||||
@ -168,27 +172,30 @@ pp.jsxReadWord = function() {
|
|||||||
// Transforms JSX element name to string.
|
// Transforms JSX element name to string.
|
||||||
|
|
||||||
function getQualifiedJSXName(object) {
|
function getQualifiedJSXName(object) {
|
||||||
if (object.type === "JSXIdentifier")
|
if (object.type === "JSXIdentifier") {
|
||||||
return object.name;
|
return object.name;
|
||||||
|
}
|
||||||
|
|
||||||
if (object.type === "JSXNamespacedName")
|
if (object.type === "JSXNamespacedName") {
|
||||||
return object.namespace.name + ":" + object.name.name;
|
return object.namespace.name + ":" + object.name.name;
|
||||||
|
}
|
||||||
|
|
||||||
if (object.type === "JSXMemberExpression")
|
if (object.type === "JSXMemberExpression") {
|
||||||
return getQualifiedJSXName(object.object) + "." +
|
return getQualifiedJSXName(object.object) + "." + getQualifiedJSXName(object.property);
|
||||||
getQualifiedJSXName(object.property);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse next token as JSX identifier
|
// Parse next token as JSX identifier
|
||||||
|
|
||||||
pp.jsxParseIdentifier = function() {
|
pp.jsxParseIdentifier = function() {
|
||||||
var node = this.startNode();
|
var node = this.startNode();
|
||||||
if (this.type === tt.jsxName)
|
if (this.type === tt.jsxName) {
|
||||||
node.name = this.value;
|
node.name = this.value;
|
||||||
else if (this.type.keyword)
|
} else if (this.type.keyword) {
|
||||||
node.name = this.type.keyword;
|
node.name = this.type.keyword;
|
||||||
else
|
} else {
|
||||||
this.unexpected();
|
this.unexpected();
|
||||||
|
}
|
||||||
this.next();
|
this.next();
|
||||||
return this.finishNode(node, "JSXIdentifier");
|
return this.finishNode(node, "JSXIdentifier");
|
||||||
};
|
};
|
||||||
@ -199,6 +206,7 @@ pp.jsxParseNamespacedName = function() {
|
|||||||
var startPos = this.start, startLoc = this.startLoc;
|
var startPos = this.start, startLoc = this.startLoc;
|
||||||
var name = this.jsxParseIdentifier();
|
var name = this.jsxParseIdentifier();
|
||||||
if (!this.eat(tt.colon)) return name;
|
if (!this.eat(tt.colon)) return name;
|
||||||
|
|
||||||
var node = this.startNodeAt(startPos, startLoc);
|
var node = this.startNodeAt(startPos, startLoc);
|
||||||
node.namespace = name;
|
node.namespace = name;
|
||||||
node.name = this.jsxParseIdentifier();
|
node.name = this.jsxParseIdentifier();
|
||||||
@ -224,18 +232,20 @@ pp.jsxParseElementName = function() {
|
|||||||
|
|
||||||
pp.jsxParseAttributeValue = function() {
|
pp.jsxParseAttributeValue = function() {
|
||||||
switch (this.type) {
|
switch (this.type) {
|
||||||
case tt.braceL:
|
case tt.braceL:
|
||||||
var node = this.jsxParseExpressionContainer();
|
var node = this.jsxParseExpressionContainer();
|
||||||
if (node.expression.type === "JSXEmptyExpression")
|
if (node.expression.type === "JSXEmptyExpression") {
|
||||||
this.raise(node.start, "JSX attributes must only be assigned a non-empty expression");
|
this.raise(node.start, "JSX attributes must only be assigned a non-empty expression");
|
||||||
return node;
|
} else {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
case tt.jsxTagStart:
|
case tt.jsxTagStart:
|
||||||
case tt.string:
|
case tt.string:
|
||||||
return this.parseExprAtom();
|
return this.parseExprAtom();
|
||||||
|
|
||||||
default:
|
default:
|
||||||
this.raise(this.start, "JSX value should be either an expression or a quoted JSX text");
|
this.raise(this.start, "JSX value should be either an expression or a quoted JSX text");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -261,9 +271,11 @@ pp.jsxParseEmptyExpression = function() {
|
|||||||
pp.jsxParseExpressionContainer = function() {
|
pp.jsxParseExpressionContainer = function() {
|
||||||
var node = this.startNode();
|
var node = this.startNode();
|
||||||
this.next();
|
this.next();
|
||||||
node.expression = this.type === tt.braceR
|
if (this.type === tt.braceR) {
|
||||||
? this.jsxParseEmptyExpression()
|
node.expression = this.jsxParseEmptyExpression();
|
||||||
: this.parseExpression();
|
} else {
|
||||||
|
node.expression = this.parseExpression();
|
||||||
|
}
|
||||||
this.expect(tt.braceR);
|
this.expect(tt.braceR);
|
||||||
return this.finishNode(node, "JSXExpressionContainer");
|
return this.finishNode(node, "JSXExpressionContainer");
|
||||||
};
|
};
|
||||||
@ -289,8 +301,9 @@ pp.jsxParseOpeningElementAt = function(startPos, startLoc) {
|
|||||||
var node = this.startNodeAt(startPos, startLoc);
|
var node = this.startNodeAt(startPos, startLoc);
|
||||||
node.attributes = [];
|
node.attributes = [];
|
||||||
node.name = this.jsxParseElementName();
|
node.name = this.jsxParseElementName();
|
||||||
while (this.type !== tt.slash && this.type !== tt.jsxTagEnd)
|
while (this.type !== tt.slash && this.type !== tt.jsxTagEnd) {
|
||||||
node.attributes.push(this.jsxParseAttribute());
|
node.attributes.push(this.jsxParseAttribute());
|
||||||
|
}
|
||||||
node.selfClosing = this.eat(tt.slash);
|
node.selfClosing = this.eat(tt.slash);
|
||||||
this.expect(tt.jsxTagEnd);
|
this.expect(tt.jsxTagEnd);
|
||||||
return this.finishNode(node, "JSXOpeningElement");
|
return this.finishNode(node, "JSXOpeningElement");
|
||||||
@ -317,32 +330,33 @@ pp.jsxParseElementAt = function(startPos, startLoc) {
|
|||||||
if (!openingElement.selfClosing) {
|
if (!openingElement.selfClosing) {
|
||||||
contents: for (;;) {
|
contents: for (;;) {
|
||||||
switch (this.type) {
|
switch (this.type) {
|
||||||
case tt.jsxTagStart:
|
case tt.jsxTagStart:
|
||||||
startPos = this.start; startLoc = this.startLoc;
|
startPos = this.start; startLoc = this.startLoc;
|
||||||
this.next();
|
this.next();
|
||||||
if (this.eat(tt.slash)) {
|
if (this.eat(tt.slash)) {
|
||||||
closingElement = this.jsxParseClosingElementAt(startPos, startLoc);
|
closingElement = this.jsxParseClosingElementAt(startPos, startLoc);
|
||||||
break contents;
|
break contents;
|
||||||
}
|
}
|
||||||
children.push(this.jsxParseElementAt(startPos, startLoc));
|
children.push(this.jsxParseElementAt(startPos, startLoc));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case tt.jsxText:
|
case tt.jsxText:
|
||||||
children.push(this.parseExprAtom());
|
children.push(this.parseExprAtom());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case tt.braceL:
|
case tt.braceL:
|
||||||
children.push(this.jsxParseExpressionContainer());
|
children.push(this.jsxParseExpressionContainer());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
this.unexpected();
|
this.unexpected();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (getQualifiedJSXName(closingElement.name) !== getQualifiedJSXName(openingElement.name)) {
|
if (getQualifiedJSXName(closingElement.name) !== getQualifiedJSXName(openingElement.name)) {
|
||||||
this.raise(
|
this.raise(
|
||||||
closingElement.start,
|
closingElement.start,
|
||||||
"Expected corresponding JSX closing tag for <" + getQualifiedJSXName(openingElement.name) + ">");
|
"Expected corresponding JSX closing tag for <" + getQualifiedJSXName(openingElement.name) + ">"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -418,4 +432,4 @@ export default function(instance) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import {reservedWords, keywords} from "./identifier";
|
import { reservedWords, keywords } from "./identifier";
|
||||||
import {types as tt} from "./tokentype";
|
import { types as tt } from "./tokentype";
|
||||||
import {lineBreak} from "./whitespace";
|
import { lineBreak } from "./whitespace";
|
||||||
|
|
||||||
export function Parser(options, input, startPos) {
|
export function Parser(options, input, startPos) {
|
||||||
this.options = options;
|
this.options = options;
|
||||||
@ -80,9 +80,7 @@ Parser.prototype.loadPlugins = function (plugins) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Parser.prototype.parse = function () {
|
Parser.prototype.parse = function () {
|
||||||
return new Promise((resolve) => {
|
let node = this.options.program || this.startNode();
|
||||||
let node = this.options.program || this.startNode();
|
this.nextToken();
|
||||||
this.nextToken();
|
return this.parseTopLevel(node);
|
||||||
resolve(this.parseTopLevel(node));
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import {types as tt} from "./tokentype";
|
import { types as tt } from "./tokentype";
|
||||||
import {Parser} from "./state";
|
import { Parser } from "./state";
|
||||||
import {lineBreak} from "./whitespace";
|
import { lineBreak } from "./whitespace";
|
||||||
|
|
||||||
const pp = Parser.prototype;
|
const pp = Parser.prototype;
|
||||||
|
|
||||||
@ -734,7 +734,7 @@ pp.parseExportSpecifiers = function () {
|
|||||||
|
|
||||||
let node = this.startNode();
|
let node = this.startNode();
|
||||||
node.local = this.parseIdent(this.type === tt._default);
|
node.local = this.parseIdent(this.type === tt._default);
|
||||||
node.exported = this.eatContextual("as") ? this.parseIdent(true) : node.local;
|
node.exported = this.eatContextual("as") ? this.parseIdent(true) : node.local.__clone();
|
||||||
nodes.push(this.finishNode(node, "ExportSpecifier"));
|
nodes.push(this.finishNode(node, "ExportSpecifier"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -792,7 +792,7 @@ pp.parseImportSpecifiers = function (node) {
|
|||||||
|
|
||||||
let specifier = this.startNode();
|
let specifier = this.startNode();
|
||||||
specifier.imported = this.parseIdent(true);
|
specifier.imported = this.parseIdent(true);
|
||||||
specifier.local = this.eatContextual("as") ? this.parseIdent() : specifier.imported;
|
specifier.local = this.eatContextual("as") ? this.parseIdent() : specifier.imported.__clone();
|
||||||
this.checkLVal(specifier.local, true);
|
this.checkLVal(specifier.local, true);
|
||||||
node.specifiers.push(this.finishNode(specifier, "ImportSpecifier"));
|
node.specifiers.push(this.finishNode(specifier, "ImportSpecifier"));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,9 +2,9 @@
|
|||||||
// given point in the program is loosely based on sweet.js' approach.
|
// given point in the program is loosely based on sweet.js' approach.
|
||||||
// See https://github.com/mozilla/sweet.js/wiki/design
|
// See https://github.com/mozilla/sweet.js/wiki/design
|
||||||
|
|
||||||
import {Parser} from "./state";
|
import { Parser } from "./state";
|
||||||
import {types as tt} from "./tokentype";
|
import { types as tt } from "./tokentype";
|
||||||
import {lineBreak} from "./whitespace";
|
import { lineBreak } from "./whitespace";
|
||||||
|
|
||||||
export class TokContext {
|
export class TokContext {
|
||||||
constructor(token, isExpr, preserveSpace, override) {
|
constructor(token, isExpr, preserveSpace, override) {
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import {isIdentifierStart, isIdentifierChar} from "./identifier";
|
import { isIdentifierStart, isIdentifierChar } from "./identifier";
|
||||||
import {types as tt, keywords as keywordTypes} from "./tokentype";
|
import { types as tt, keywords as keywordTypes } from "./tokentype";
|
||||||
import {Parser} from "./state";
|
import { Parser } from "./state";
|
||||||
import {SourceLocation} from "./location";
|
import { SourceLocation } from "./location";
|
||||||
import {lineBreak, lineBreakG, isNewLine, nonASCIIwhitespace} from "./whitespace";
|
import { lineBreak, lineBreakG, isNewLine, nonASCIIwhitespace } from "./whitespace";
|
||||||
|
|
||||||
// Object type used to represent tokens. Note that normally, tokens
|
// Object type used to represent tokens. Note that normally, tokens
|
||||||
// simply exist as properties on the parser object. This is only
|
// simply exist as properties on the parser object. This is only
|
||||||
@ -123,14 +123,15 @@ pp.skipBlockComment = function () {
|
|||||||
pp.skipLineComment = function (startSkip) {
|
pp.skipLineComment = function (startSkip) {
|
||||||
let start = this.pos;
|
let start = this.pos;
|
||||||
let startLoc = this.options.onComment && this.curPosition();
|
let startLoc = this.options.onComment && this.curPosition();
|
||||||
let ch = this.input.charCodeAt(this.pos+=startSkip);
|
let ch = this.input.charCodeAt(this.pos += startSkip);
|
||||||
while (this.pos < this.input.length && ch !== 10 && ch !== 13 && ch !== 8232 && ch !== 8233) {
|
while (this.pos < this.input.length && ch !== 10 && ch !== 13 && ch !== 8232 && ch !== 8233) {
|
||||||
++this.pos;
|
++this.pos;
|
||||||
ch = this.input.charCodeAt(this.pos);
|
ch = this.input.charCodeAt(this.pos);
|
||||||
}
|
}
|
||||||
if (this.options.onComment)
|
if (this.options.onComment) {
|
||||||
this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos,
|
this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos,
|
||||||
startLoc, this.curPosition());
|
startLoc, this.curPosition());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Called at the start of the parse and after every token. Skips
|
// Called at the start of the parse and after every token. Skips
|
||||||
@ -143,10 +144,12 @@ pp.skipSpace = function() {
|
|||||||
case 32: case 160: // ' '
|
case 32: case 160: // ' '
|
||||||
++this.pos;
|
++this.pos;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 13:
|
case 13:
|
||||||
if (this.input.charCodeAt(this.pos + 1) === 10) {
|
if (this.input.charCodeAt(this.pos + 1) === 10) {
|
||||||
++this.pos;
|
++this.pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 10: case 8232: case 8233:
|
case 10: case 8232: case 8233:
|
||||||
++this.pos;
|
++this.pos;
|
||||||
if (this.options.locations) {
|
if (this.options.locations) {
|
||||||
@ -154,18 +157,22 @@ pp.skipSpace = function() {
|
|||||||
this.lineStart = this.pos;
|
this.lineStart = this.pos;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 47: // '/'
|
case 47: // '/'
|
||||||
switch (this.input.charCodeAt(this.pos + 1)) {
|
switch (this.input.charCodeAt(this.pos + 1)) {
|
||||||
case 42: // '*'
|
case 42: // '*'
|
||||||
this.skipBlockComment();
|
this.skipBlockComment();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 47:
|
case 47:
|
||||||
this.skipLineComment(2);
|
this.skipLineComment(2);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break loop;
|
break loop;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) {
|
if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) {
|
||||||
++this.pos;
|
++this.pos;
|
||||||
@ -402,28 +409,35 @@ pp.finishOp = function (type, size) {
|
|||||||
return this.finishToken(type, str);
|
return this.finishToken(type, str);
|
||||||
};
|
};
|
||||||
|
|
||||||
var regexpUnicodeSupport = false;
|
|
||||||
try {
|
|
||||||
new RegExp("\uffff", "u");
|
|
||||||
regexpUnicodeSupport = true;
|
|
||||||
} catch(e) {}
|
|
||||||
|
|
||||||
// Parse a regular expression. Some context-awareness is necessary,
|
// Parse a regular expression. Some context-awareness is necessary,
|
||||||
// since a '/' inside a '[]' set does not end the expression.
|
// since a '/' inside a '[]' set does not end the expression.
|
||||||
|
|
||||||
pp.readRegexp = function () {
|
function tryCreateRegexp(src, flags, throwErrorStart) {
|
||||||
|
try {
|
||||||
|
return new RegExp(src, flags);
|
||||||
|
} catch (e) {
|
||||||
|
if (throwErrorStart !== undefined) {
|
||||||
|
if (e instanceof SyntaxError) this.raise(throwErrorStart, "Error parsing regular expression: " + e.message);
|
||||||
|
this.raise(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var regexpUnicodeSupport = !!tryCreateRegexp("\uffff", "u");
|
||||||
|
|
||||||
|
pp.readRegexp = function() {
|
||||||
let escaped, inClass, start = this.pos;
|
let escaped, inClass, start = this.pos;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (this.pos >= this.input.length) this.raise(start, "Unterminated regular expression");
|
if (this.pos >= this.input.length) this.raise(start, "Unterminated regular expression");
|
||||||
let ch = this.input.charAt(this.pos);
|
let ch = this.input.charAt(this.pos);
|
||||||
if (lineBreak.test(ch)) this.raise(start, "Unterminated regular expression");
|
if (lineBreak.test(ch)) this.raise(start, "Unterminated regular expression");
|
||||||
if (!escaped) {
|
if (escaped) {
|
||||||
|
escaped = false;
|
||||||
|
} else {
|
||||||
if (ch === "[") inClass = true;
|
if (ch === "[") inClass = true;
|
||||||
else if (ch === "]" && inClass) inClass = false;
|
else if (ch === "]" && inClass) inClass = false;
|
||||||
else if (ch === "/" && !inClass) break;
|
else if (ch === "/" && !inClass) break;
|
||||||
escaped = ch === "\\";
|
escaped = ch === "\\";
|
||||||
} else {
|
|
||||||
escaped = false;
|
|
||||||
}
|
}
|
||||||
++this.pos;
|
++this.pos;
|
||||||
}
|
}
|
||||||
@ -456,23 +470,14 @@ pp.readRegexp = function () {
|
|||||||
}
|
}
|
||||||
// Detect invalid regular expressions.
|
// Detect invalid regular expressions.
|
||||||
let value = null;
|
let value = null;
|
||||||
|
|
||||||
// Rhino's regular expression parser is flaky and throws uncatchable exceptions,
|
// Rhino's regular expression parser is flaky and throws uncatchable exceptions,
|
||||||
// so don't do detection if we are running under Rhino
|
// so don't do detection if we are running under Rhino
|
||||||
if (!isRhino) {
|
if (!isRhino) {
|
||||||
try {
|
tryCreateRegexp(tmp, undefined, start);
|
||||||
new RegExp(tmp);
|
|
||||||
} catch (e) {
|
|
||||||
if (e instanceof SyntaxError) this.raise(start, `Error parsing regular expression: ${e.message}`);
|
|
||||||
this.raise(e);
|
|
||||||
}
|
|
||||||
// Get a regular expression object for this pattern-flag pair, or `null` in
|
// Get a regular expression object for this pattern-flag pair, or `null` in
|
||||||
// case the current environment doesn't support the flags it uses.
|
// case the current environment doesn't support the flags it uses.
|
||||||
try {
|
value = tryCreateRegexp(content, mods);
|
||||||
value = new RegExp(content, mods);
|
|
||||||
} catch (err) {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.finishToken(tt.regexp, {pattern: content, flags: mods, value: value});
|
return this.finishToken(tt.regexp, {pattern: content, flags: mods, value: value});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -27,24 +27,9 @@ function runTest(test) {
|
|||||||
if (expected.onToken = testOpts.onToken)
|
if (expected.onToken = testOpts.onToken)
|
||||||
testOpts.onToken = [];
|
testOpts.onToken = [];
|
||||||
|
|
||||||
return parse(test.code, testOpts).then(function (ast) {
|
try {
|
||||||
if (test.error) {
|
var ast = parse(test.code, testOpts);
|
||||||
throw new Error("Expected error message: " + test.error + ". But parsing succeeded.");
|
} catch (err) {
|
||||||
} else if (test.assert) {
|
|
||||||
var error = test.assert(ast);
|
|
||||||
if (error) throw new Error("Assertion failed: " + error);
|
|
||||||
} else {
|
|
||||||
var mis = misMatch(test.ast, ast);
|
|
||||||
for (var name in expected) {
|
|
||||||
if (mis) break;
|
|
||||||
if (expected[name]) {
|
|
||||||
mis = misMatch(expected[name], testOpts[name]);
|
|
||||||
testOpts[name] = expected[name];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (mis) throw new Error(mis);
|
|
||||||
}
|
|
||||||
}, function (err) {
|
|
||||||
if (test.error) {
|
if (test.error) {
|
||||||
if (err.message === test.error) {
|
if (err.message === test.error) {
|
||||||
return;
|
return;
|
||||||
@ -54,7 +39,24 @@ function runTest(test) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
throw err;
|
throw err;
|
||||||
});
|
}
|
||||||
|
|
||||||
|
if (test.error) {
|
||||||
|
throw new Error("Expected error message: " + test.error + ". But parsing succeeded.");
|
||||||
|
} else if (test.assert) {
|
||||||
|
var error = test.assert(ast);
|
||||||
|
if (error) throw new Error("Assertion failed: " + error);
|
||||||
|
} else {
|
||||||
|
var mis = misMatch(test.ast, ast);
|
||||||
|
for (var name in expected) {
|
||||||
|
if (mis) break;
|
||||||
|
if (expected[name]) {
|
||||||
|
mis = misMatch(expected[name], testOpts[name]);
|
||||||
|
testOpts[name] = expected[name];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mis) throw new Error(mis);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function ppJSON(v) { return v instanceof RegExp ? v.toString() : JSON.stringify(v, null, 2); }
|
function ppJSON(v) { return v instanceof RegExp ? v.toString() : JSON.stringify(v, null, 2); }
|
||||||
|
|||||||
@ -3636,7 +3636,9 @@ if (typeof exports !== "undefined") {
|
|||||||
var testFail = require("./driver.js").testFail;
|
var testFail = require("./driver.js").testFail;
|
||||||
}
|
}
|
||||||
|
|
||||||
testFail("var x = <div>one</div><div>two</div>;", "Adjacent JSX elements must be wrapped in an enclosing tag (1:22)");
|
testFail("var x = <div>one</div><div>two</div>;", "Adjacent JSX elements must be wrapped in an enclosing tag (1:22)", {
|
||||||
|
plugins: { jsx: true }
|
||||||
|
});
|
||||||
|
|
||||||
for (var ns in fbTestFixture) {
|
for (var ns in fbTestFixture) {
|
||||||
ns = fbTestFixture[ns];
|
ns = fbTestFixture[ns];
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user