more architectural changes
This commit is contained in:
parent
afe5eb118c
commit
a226641631
@ -19,7 +19,8 @@
|
||||
"no-loop-func": 0,
|
||||
"no-unreachable": 0,
|
||||
"no-labels": 0,
|
||||
"no-process-exit": 0
|
||||
"no-process-exit": 0,
|
||||
"camelcase": 0
|
||||
},
|
||||
"env": {
|
||||
"node": true
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,6 +1,6 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
test/core/tmp
|
||||
test/tmp
|
||||
*.log
|
||||
*.cache
|
||||
/templates.json
|
||||
|
||||
@ -6,7 +6,6 @@ cache:
|
||||
|
||||
node_js:
|
||||
- iojs
|
||||
- "0.8"
|
||||
- "0.10"
|
||||
- "0.12"
|
||||
|
||||
|
||||
@ -10,6 +10,4 @@ commander.option("-t, --output-type [type]", "Type of output (global|umd|var)",
|
||||
commander.usage("[options]");
|
||||
commander.parse(process.argv);
|
||||
|
||||
util.ensureTemplates().then(function () {
|
||||
console.log(runtime(commander.whitelist, commander.outputType));
|
||||
});
|
||||
|
||||
@ -35,7 +35,7 @@ exports.transform = function (filename, code, opts) {
|
||||
opts.ignore = null;
|
||||
opts.only = null;
|
||||
|
||||
var result = babel.__plsDontUseThis(code, opts);
|
||||
var result = babel.transform(code, opts);
|
||||
result.filename = filename;
|
||||
result.actual = code;
|
||||
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 fs from "fs";
|
||||
|
||||
var deasync;
|
||||
try {
|
||||
deasync = require("deasync");
|
||||
} catch (err) {}
|
||||
|
||||
export { util, babylon as acorn, transform };
|
||||
export { pipeline } from "../transformation";
|
||||
export { canCompile } from "../util";
|
||||
@ -42,32 +37,24 @@ export function transformFile(filename: string, opts?: Object, callback: Functio
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
export function __plsDontUseThis(code, opts) {
|
||||
if (!deasync) {
|
||||
throw new Error("Sorry, this API isn't available in the current environment.");
|
||||
}
|
||||
|
||||
var done = false;
|
||||
var result, err;
|
||||
|
||||
transform(code, opts).then(function (_result) {
|
||||
result = _result;
|
||||
done = true;
|
||||
}, function (_err) {
|
||||
err = _err;
|
||||
done = true;
|
||||
callback(null, result);
|
||||
});
|
||||
|
||||
deasync.loopWhile(() => !done);
|
||||
|
||||
if (err) {
|
||||
throw err;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
|
||||
export function transformFileSync(filename: string, opts?: Object = {}) {
|
||||
opts.filename = filename;
|
||||
return transform(fs.readFileSync(filename, "utf8"), opts);
|
||||
}
|
||||
|
||||
export function parse(code, opts = {}) {
|
||||
|
||||
@ -57,7 +57,7 @@ var compile = function (filename, opts = {}) {
|
||||
optsManager.mergeOptions(transformOpts);
|
||||
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;
|
||||
if (env) cacheKey += `:${env}`;
|
||||
@ -70,8 +70,7 @@ var compile = function (filename, opts = {}) {
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
var file = fs.readFileSync(filename, "utf8");
|
||||
result = babel.__plsDontUseThis(file, extend(opts, {
|
||||
result = babel.transformFileSync(filename, extend(opts, {
|
||||
sourceMap: "both",
|
||||
ast: false
|
||||
}));
|
||||
|
||||
@ -45,9 +45,8 @@ export default function (code, opts = {}) {
|
||||
parseOpts.plugins.flow = true;
|
||||
}
|
||||
|
||||
return babylon.parse(code, parseOpts).then(function (ast) {
|
||||
var ast = babylon.parse(code, parseOpts);
|
||||
estraverse.attachComments(ast, comments, tokens);
|
||||
ast = normalizeAst(ast, comments, commentsAndTokens);
|
||||
return ast;
|
||||
});
|
||||
}
|
||||
|
||||
@ -12,7 +12,6 @@ import defaults from "lodash/object/defaults";
|
||||
import includes from "lodash/collection/includes";
|
||||
import traverse from "../../traversal";
|
||||
import Logger from "./logger";
|
||||
import { Promise } from "bluebird";
|
||||
import Plugin from "../plugin";
|
||||
import parse from "../../helpers/parse";
|
||||
import Hub from "../../traversal/hub";
|
||||
@ -429,10 +428,9 @@ export default class File {
|
||||
parseOpts.sourceType = "module";
|
||||
|
||||
this.log.debug("Parse start");
|
||||
return parse(code, parseOpts).then((ast) => {
|
||||
var ast = parse(code, parseOpts);
|
||||
this.log.debug("Parse stop");
|
||||
return ast;
|
||||
});
|
||||
}
|
||||
|
||||
_addAst(ast) {
|
||||
@ -467,11 +465,7 @@ export default class File {
|
||||
}
|
||||
this.call("post");
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
util.ensureTemplates().then(() => {
|
||||
resolve(this.generate());
|
||||
}, reject);
|
||||
});
|
||||
return this.generate();
|
||||
}
|
||||
|
||||
wrap(code, callback) {
|
||||
@ -479,7 +473,7 @@ export default class File {
|
||||
|
||||
try {
|
||||
if (this.shouldIgnore()) {
|
||||
return Promise.resolve(this.makeResult({ code, ignored: true }));
|
||||
return this.makeResult({ code, ignored: true });
|
||||
} else {
|
||||
return callback();
|
||||
}
|
||||
@ -519,9 +513,8 @@ export default class File {
|
||||
|
||||
parseCode() {
|
||||
this.parseShebang();
|
||||
return this.parse(this.code).then((ast) => {
|
||||
var ast = this.parse(this.code);
|
||||
this.addAst(ast);
|
||||
});
|
||||
}
|
||||
|
||||
shouldIgnore() {
|
||||
@ -567,6 +560,10 @@ export default class File {
|
||||
map: map
|
||||
};
|
||||
|
||||
result.then = function (callback) {
|
||||
callback(result);
|
||||
};
|
||||
|
||||
if (this.opts.code) {
|
||||
result.code = code;
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import PluginManager from "./file/plugin-manager";
|
||||
import normalizeAst from "../helpers/normalize-ast";
|
||||
import { Promise } from "bluebird";
|
||||
import Plugin from "./plugin";
|
||||
import assign from "lodash/object/assign";
|
||||
import object from "../helpers/object";
|
||||
@ -91,20 +90,19 @@ export default class Pipeline {
|
||||
var file = new File(opts, this);
|
||||
return file.wrap(code, function () {
|
||||
file.addCode(code);
|
||||
return file.parseCode(code).then(() => file.transform());
|
||||
file.parseCode(code);
|
||||
return file.transform();
|
||||
});
|
||||
}
|
||||
|
||||
transformFromAst(ast, code, opts) {
|
||||
return new Promise((resolve) => {
|
||||
ast = normalizeAst(ast);
|
||||
|
||||
var file = new File(opts, this);
|
||||
resolve(file.wrap(code, function () {
|
||||
return file.wrap(code, function () {
|
||||
file.addCode(code);
|
||||
file.addAst(ast);
|
||||
return file.transform();
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -5,7 +5,6 @@ export default {
|
||||
//- builtin-pre
|
||||
strict: require("./other/strict"),
|
||||
eval: require("babel-plugin-eval"),
|
||||
_explode: require("./internal/explode"),
|
||||
_validation: require("./internal/validation"),
|
||||
_hoistDirectives: require("./internal/hoist-directives"),
|
||||
"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 isString from "lodash/lang/isString";
|
||||
import isRegExp from "lodash/lang/isRegExp";
|
||||
import { Promise } from "bluebird";
|
||||
import Module from "module";
|
||||
import isEmpty from "lodash/lang/isEmpty";
|
||||
import parse from "./helpers/parse";
|
||||
@ -157,8 +156,6 @@ var templateVisitor = {
|
||||
//
|
||||
|
||||
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];
|
||||
if (!ast) throw new ReferenceError(`unknown template ${name}`);
|
||||
|
||||
@ -183,11 +180,10 @@ export function template(name: string, nodes?: Array<Object>, keepExpression?: b
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
export function parseTemplate(loc: string, code: string): Object {
|
||||
return parse(code, { filename: loc, looseModules: true }).then(function (ast) {
|
||||
return traverse.removeProperties(ast.program);
|
||||
});
|
||||
var ast = parse(code, { filename: loc, looseModules: true }).program;
|
||||
ast = traverse.removeProperties(ast);
|
||||
return ast;
|
||||
}
|
||||
|
||||
function loadTemplates() {
|
||||
@ -198,37 +194,22 @@ function loadTemplates() {
|
||||
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)) {
|
||||
if (name[0] === ".") continue;
|
||||
var key = path.basename(name, path.extname(name));
|
||||
var loc = path.join(templatesLoc, name);
|
||||
var code = fs.readFileSync(loc, "utf8");
|
||||
|
||||
let key = path.basename(name, path.extname(name));
|
||||
let loc = path.join(templatesLoc, name);
|
||||
let code = fs.readFileSync(loc, "utf8");
|
||||
|
||||
promises.push(parseTemplate(loc, code).then(function (template) {
|
||||
templates[key] = template;
|
||||
}));
|
||||
templates[key] = parseTemplate(loc, code);
|
||||
}
|
||||
|
||||
return Promise.all(promises).then(function () {
|
||||
return exports.templates = templates;
|
||||
});
|
||||
}
|
||||
|
||||
export function ensureTemplates() {
|
||||
return new Promise((resolve) => {
|
||||
if (exports.templates) {
|
||||
resolve(exports.templates);
|
||||
} else {
|
||||
resolve(loadTemplates());
|
||||
}
|
||||
});
|
||||
return templates;
|
||||
}
|
||||
|
||||
try {
|
||||
exports.templates = require("../templates.json");
|
||||
exports.templates = require("../../templates.json");
|
||||
} catch (err) {
|
||||
if (err.code !== "MODULE_NOT_FOUND") throw err;
|
||||
exports.templates = loadTemplates();
|
||||
}
|
||||
|
||||
@ -12,12 +12,7 @@ var _ = require("lodash");
|
||||
|
||||
require("../lib/polyfill");
|
||||
|
||||
var doneBeforeEval = false;
|
||||
function beforeEval() {
|
||||
if (doneBeforeEval) return;
|
||||
doneBeforeEval = true;
|
||||
eval(buildExernalHelpers());
|
||||
}
|
||||
|
||||
global.assertNoOwnProperties = function (obj) {
|
||||
assert.equal(Object.getOwnPropertyNames(obj).length, 0);
|
||||
@ -49,7 +44,6 @@ chai.assert.throw = function (fn, msg) {
|
||||
|
||||
return chai.assert._throw(fn, msg);
|
||||
};
|
||||
|
||||
var run = function (task, done) {
|
||||
var actual = task.actual;
|
||||
var expect = task.expect;
|
||||
@ -74,10 +68,8 @@ var run = function (task, done) {
|
||||
helper.esvalid(result.ast.program, result.code, opts.loc);
|
||||
};
|
||||
|
||||
var promises = [];
|
||||
|
||||
if (execCode) {
|
||||
promises.push(transform(execCode, getOpts(exec)).then(function (result) {
|
||||
result = transform(execCode, getOpts(exec));
|
||||
execCode = result.code;
|
||||
|
||||
try {
|
||||
@ -91,9 +83,8 @@ var run = function (task, done) {
|
||||
}
|
||||
};
|
||||
|
||||
var fn = new Function("require", "exports", execCode);
|
||||
beforeEval();
|
||||
fn.call(global, fakeRequire, {});
|
||||
var fn = new Function("require", "done", "exports", execCode);
|
||||
fn.call(global, fakeRequire, chai.assert, {}, done);
|
||||
} catch (err) {
|
||||
err.message = exec.loc + ": " + err.message;
|
||||
err.message += codeFrame(execCode);
|
||||
@ -101,13 +92,12 @@ var run = function (task, done) {
|
||||
}
|
||||
|
||||
checkAst(result, exec);
|
||||
}));
|
||||
}
|
||||
|
||||
var actualCode = actual.code;
|
||||
var expectCode = expect.code;
|
||||
if (!execCode || actualCode) {
|
||||
promises.push(transform(actualCode, getOpts(actual)).then(function (result) {
|
||||
result = transform(actualCode, getOpts(actual));
|
||||
actualCode = result.code.trim();
|
||||
|
||||
try {
|
||||
@ -118,6 +108,7 @@ var run = function (task, done) {
|
||||
}
|
||||
|
||||
checkAst(result, actual);
|
||||
}
|
||||
|
||||
if (task.sourceMap) {
|
||||
chai.expect(result.map).to.deep.equal(task.sourceMap);
|
||||
@ -133,12 +124,6 @@ var run = function (task, done) {
|
||||
chai.expect({ line: expect.line, column: expect.column }).to.deep.equal(actual);
|
||||
});
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
Promise.all(promises).then(function () {
|
||||
done()
|
||||
}, done);
|
||||
};
|
||||
|
||||
module.exports = function (suiteOpts, taskOpts, dynamicOpts) {
|
||||
@ -155,7 +140,11 @@ module.exports = function (suiteOpts, taskOpts, dynamicOpts) {
|
||||
_.each(testSuite.tests, function (task) {
|
||||
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);
|
||||
if (dynamicOpts) dynamicOpts(task.options, task);
|
||||
|
||||
@ -165,26 +154,24 @@ module.exports = function (suiteOpts, taskOpts, dynamicOpts) {
|
||||
// the options object with useless options
|
||||
delete task.options.throws;
|
||||
|
||||
return run(task, function (err) {
|
||||
if (err) {
|
||||
// we just wanted any error message
|
||||
if (throwMsg === true) return done();
|
||||
assert.throws(runTask, function (err) {
|
||||
return throwMsg === true || err.message.indexOf(throwMsg) >= 0;
|
||||
});
|
||||
} else {
|
||||
runTask();
|
||||
}
|
||||
};
|
||||
|
||||
if (err.message.indexOf(throwMsg) >= 0) {
|
||||
// success!
|
||||
done();
|
||||
var callback;
|
||||
if (task.options.asyncExec) {
|
||||
callback = runTest;
|
||||
} else {
|
||||
// didn't include it :(
|
||||
done(new Error("Expected an error message of " + JSON.stringify(throwMsg) + " but got " + JSON.stringify(err.message)));
|
||||
callback = function () {
|
||||
return runTest();
|
||||
};
|
||||
}
|
||||
} else {
|
||||
done(new Error("Expected an error message but got none"));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return run(task, done);
|
||||
}
|
||||
});
|
||||
|
||||
test(task.title, !task.disabled && callback);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -2,5 +2,5 @@
|
||||
|
||||
var A = "a";
|
||||
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", {
|
||||
value: true
|
||||
});
|
||||
function f(a) {
|
||||
|
||||
exports.f = function f(a) {
|
||||
return !a;
|
||||
}
|
||||
|
||||
exports.f = f;
|
||||
|
||||
};
|
||||
|
||||
@ -34,9 +34,7 @@ function* x() {
|
||||
}
|
||||
}
|
||||
|
||||
function y() {
|
||||
exports.y = function y() {
|
||||
return [].concat(babelHelpers.toConsumableArray(x()));
|
||||
}
|
||||
|
||||
exports.y = y;
|
||||
};
|
||||
|
||||
|
||||
@ -22,11 +22,11 @@ suite("generation", function () {
|
||||
_.each(helper.get("generation"), function (testSuite) {
|
||||
suite("generation/" + testSuite.title, function () {
|
||||
_.each(testSuite.tests, function (task) {
|
||||
test(task.title, !task.disabled && function (done) {
|
||||
test(task.title, !task.disabled && function () {
|
||||
var expect = task.expect;
|
||||
var actual = task.actual;
|
||||
|
||||
parse(actual.code, {
|
||||
var actualAst = parse(actual.code, {
|
||||
filename: actual.loc,
|
||||
nonStandard: true,
|
||||
strictMode: false,
|
||||
@ -38,11 +38,10 @@ _.each(helper.get("generation"), function (testSuite) {
|
||||
"es7.exportExtensions": 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);
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -12,16 +12,10 @@ suite("util", function () {
|
||||
|
||||
test("templates do not recurse", function () {
|
||||
var key = __filename;
|
||||
var KEY = parse("replacedKey").program.body[0].expression;
|
||||
var VALUE = parse("+KEY").program.body[0].expression;
|
||||
|
||||
|
||||
return parse("replacedKey").then(function (result) {
|
||||
var KEY = result.program.body[0].expression;
|
||||
|
||||
return parse("+KEY").then(function (result) {
|
||||
var VALUE = result.program.body[0].expression;
|
||||
|
||||
return util.parseTemplate(key, "KEY = VALUE;").then(function (template) {
|
||||
util.templates[key] = template;
|
||||
util.templates[key] = util.parseTemplate(key, "KEY = VALUE;");
|
||||
var result = util.template(key, { KEY: KEY, VALUE: VALUE });
|
||||
delete util.templates[key];
|
||||
|
||||
@ -31,9 +25,6 @@ suite("util", function () {
|
||||
"template should not recurse into replaced nodes, replacing KEY inside VALUE"
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test("canCompile", function () {
|
||||
assert.ok(util.canCompile("test.js"));
|
||||
|
||||
@ -3,5 +3,13 @@
|
||||
</p>
|
||||
|
||||
<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>
|
||||
|
||||
----
|
||||
|
||||
## 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/",
|
||||
"license": "MIT",
|
||||
"repository": "babel/babel",
|
||||
"main": "lib/index.js",
|
||||
"dependencies": {
|
||||
"bluebird": "^2.9.33"
|
||||
}
|
||||
"main": "lib/index.js"
|
||||
}
|
||||
|
||||
@ -19,7 +19,6 @@
|
||||
import { types as tt } from "./tokentype";
|
||||
import { Parser } from "./state";
|
||||
import { reservedWords } from "./identifier";
|
||||
import {has} from "./util";
|
||||
|
||||
const pp = Parser.prototype;
|
||||
|
||||
@ -29,14 +28,15 @@ const pp = Parser.prototype;
|
||||
// strict mode, init properties are also not allowed to be repeated.
|
||||
|
||||
pp.checkPropClash = function (prop, propHash) {
|
||||
if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand))
|
||||
return;
|
||||
if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand)) return;
|
||||
|
||||
let key = prop.key, name;
|
||||
switch (key.type) {
|
||||
case "Identifier": name = key.name; break;
|
||||
case "Literal": name = String(key.value); break;
|
||||
default: return;
|
||||
}
|
||||
|
||||
let kind = prop.kind;
|
||||
if (this.options.ecmaVersion >= 6) {
|
||||
if (name === "__proto__" && kind === "init") {
|
||||
@ -45,6 +45,7 @@ pp.checkPropClash = function (prop, propHash) {
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let other;
|
||||
if (propHash[name]) {
|
||||
other = propHash[name];
|
||||
@ -196,10 +197,11 @@ pp.parseMaybeUnary = function (refShorthandDefaultPos) {
|
||||
this.next();
|
||||
node.argument = this.parseMaybeUnary();
|
||||
if (refShorthandDefaultPos && refShorthandDefaultPos.start) this.unexpected(refShorthandDefaultPos.start);
|
||||
if (update) this.checkLVal(node.argument);
|
||||
else if (this.strict && node.operator === "delete" &&
|
||||
node.argument.type === "Identifier")
|
||||
if (update) {
|
||||
this.checkLVal(node.argument);
|
||||
} else if (this.strict && node.operator === "delete" && node.argument.type === "Identifier") {
|
||||
this.raise(node.start, "Deleting local variable in strict mode");
|
||||
}
|
||||
return this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression");
|
||||
}
|
||||
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.options.allowReserved && this.isReservedWord(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) {
|
||||
if (!refShorthandDefaultPos.start)
|
||||
refShorthandDefaultPos.start = this.start;
|
||||
prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key);
|
||||
prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key.__clone());
|
||||
} else {
|
||||
prop.value = prop.key;
|
||||
prop.value = prop.key.__clone();
|
||||
}
|
||||
prop.shorthand = true;
|
||||
} else {
|
||||
|
||||
@ -1,24 +1,3 @@
|
||||
// Acorn is a tiny, fast JavaScript parser written in JavaScript.
|
||||
//
|
||||
// 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";
|
||||
@ -45,13 +24,6 @@ import jsxPlugin from "./plugins/jsx";
|
||||
plugins.flow = flowPlugin;
|
||||
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) {
|
||||
return new Parser(getOptions(options), input).parse();
|
||||
}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { types as tt } from "./tokentype";
|
||||
import { Parser } from "./state";
|
||||
import { reservedWords } from "./identifier";
|
||||
import {has} from "./util";
|
||||
|
||||
const pp = Parser.prototype;
|
||||
|
||||
|
||||
@ -10,14 +10,28 @@ export class Node {
|
||||
this.type = "";
|
||||
this.start = pos;
|
||||
this.end = 0;
|
||||
if (parser.options.locations)
|
||||
|
||||
if (parser) {
|
||||
if (parser.options.locations) {
|
||||
this.loc = new SourceLocation(parser, loc);
|
||||
if (parser.options.directSourceFile)
|
||||
}
|
||||
|
||||
if (parser.options.directSourceFile) {
|
||||
this.sourceFile = parser.options.directSourceFile;
|
||||
if (parser.options.ranges)
|
||||
}
|
||||
|
||||
if (parser.options.ranges) {
|
||||
this.range = [pos, 0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__clone() {
|
||||
var node2 = new Node;
|
||||
for (var key in this) node2[key] = this[key];
|
||||
return node2;
|
||||
}
|
||||
}
|
||||
|
||||
pp.startNode = function () {
|
||||
return new Node(this, this.start, this.startLoc);
|
||||
|
||||
@ -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 { Parser } from "../../state";
|
||||
import { isIdentifierChar, isIdentifierStart } from "../../identifier";
|
||||
import { isNewLine, lineBreak, lineBreakG } from "../../whitespace";
|
||||
import { isNewLine } from "../../whitespace";
|
||||
|
||||
const HEX_NUMBER = /^[\da-fA-F]+$/;
|
||||
const DECIMAL_NUMBER = /^\d+$/;
|
||||
@ -40,8 +40,10 @@ var pp = Parser.prototype;
|
||||
pp.jsxReadToken = function() {
|
||||
var out = "", chunkStart = this.pos;
|
||||
for (;;) {
|
||||
if (this.pos >= this.input.length)
|
||||
if (this.pos >= this.input.length) {
|
||||
this.raise(this.start, "Unterminated JSX contents");
|
||||
}
|
||||
|
||||
var ch = this.input.charCodeAt(this.pos);
|
||||
|
||||
switch (ch) {
|
||||
@ -96,8 +98,10 @@ pp.jsxReadNewLine = function(normalizeCRLF) {
|
||||
pp.jsxReadString = function(quote) {
|
||||
var out = "", chunkStart = ++this.pos;
|
||||
for (;;) {
|
||||
if (this.pos >= this.input.length)
|
||||
if (this.pos >= this.input.length) {
|
||||
this.raise(this.start, "Unterminated string constant");
|
||||
}
|
||||
|
||||
var ch = this.input.charCodeAt(this.pos);
|
||||
if (ch === quote) break;
|
||||
if (ch === 38) { // "&"
|
||||
@ -119,8 +123,8 @@ pp.jsxReadString = function(quote) {
|
||||
pp.jsxReadEntity = function() {
|
||||
var str = "", count = 0, entity;
|
||||
var ch = this.input[this.pos];
|
||||
if (ch !== "&")
|
||||
this.raise(this.pos, "Entity must start with an ampersand");
|
||||
if (ch !== "&") this.raise(this.pos, "Entity must start with an ampersand");
|
||||
|
||||
var startPos = ++this.pos;
|
||||
while (this.pos < this.input.length && count++ < 10) {
|
||||
ch = this.input[this.pos++];
|
||||
@ -168,27 +172,30 @@ pp.jsxReadWord = function() {
|
||||
// Transforms JSX element name to string.
|
||||
|
||||
function getQualifiedJSXName(object) {
|
||||
if (object.type === "JSXIdentifier")
|
||||
if (object.type === "JSXIdentifier") {
|
||||
return object.name;
|
||||
}
|
||||
|
||||
if (object.type === "JSXNamespacedName")
|
||||
if (object.type === "JSXNamespacedName") {
|
||||
return object.namespace.name + ":" + object.name.name;
|
||||
}
|
||||
|
||||
if (object.type === "JSXMemberExpression")
|
||||
return getQualifiedJSXName(object.object) + "." +
|
||||
getQualifiedJSXName(object.property);
|
||||
if (object.type === "JSXMemberExpression") {
|
||||
return getQualifiedJSXName(object.object) + "." + getQualifiedJSXName(object.property);
|
||||
}
|
||||
}
|
||||
|
||||
// Parse next token as JSX identifier
|
||||
|
||||
pp.jsxParseIdentifier = function() {
|
||||
var node = this.startNode();
|
||||
if (this.type === tt.jsxName)
|
||||
if (this.type === tt.jsxName) {
|
||||
node.name = this.value;
|
||||
else if (this.type.keyword)
|
||||
} else if (this.type.keyword) {
|
||||
node.name = this.type.keyword;
|
||||
else
|
||||
} else {
|
||||
this.unexpected();
|
||||
}
|
||||
this.next();
|
||||
return this.finishNode(node, "JSXIdentifier");
|
||||
};
|
||||
@ -199,6 +206,7 @@ pp.jsxParseNamespacedName = function() {
|
||||
var startPos = this.start, startLoc = this.startLoc;
|
||||
var name = this.jsxParseIdentifier();
|
||||
if (!this.eat(tt.colon)) return name;
|
||||
|
||||
var node = this.startNodeAt(startPos, startLoc);
|
||||
node.namespace = name;
|
||||
node.name = this.jsxParseIdentifier();
|
||||
@ -226,9 +234,11 @@ pp.jsxParseAttributeValue = function() {
|
||||
switch (this.type) {
|
||||
case tt.braceL:
|
||||
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");
|
||||
} else {
|
||||
return node;
|
||||
}
|
||||
|
||||
case tt.jsxTagStart:
|
||||
case tt.string:
|
||||
@ -261,9 +271,11 @@ pp.jsxParseEmptyExpression = function() {
|
||||
pp.jsxParseExpressionContainer = function() {
|
||||
var node = this.startNode();
|
||||
this.next();
|
||||
node.expression = this.type === tt.braceR
|
||||
? this.jsxParseEmptyExpression()
|
||||
: this.parseExpression();
|
||||
if (this.type === tt.braceR) {
|
||||
node.expression = this.jsxParseEmptyExpression();
|
||||
} else {
|
||||
node.expression = this.parseExpression();
|
||||
}
|
||||
this.expect(tt.braceR);
|
||||
return this.finishNode(node, "JSXExpressionContainer");
|
||||
};
|
||||
@ -289,8 +301,9 @@ pp.jsxParseOpeningElementAt = function(startPos, startLoc) {
|
||||
var node = this.startNodeAt(startPos, startLoc);
|
||||
node.attributes = [];
|
||||
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.selfClosing = this.eat(tt.slash);
|
||||
this.expect(tt.jsxTagEnd);
|
||||
return this.finishNode(node, "JSXOpeningElement");
|
||||
@ -342,7 +355,8 @@ pp.jsxParseElementAt = function(startPos, startLoc) {
|
||||
if (getQualifiedJSXName(closingElement.name) !== getQualifiedJSXName(openingElement.name)) {
|
||||
this.raise(
|
||||
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) {
|
||||
}
|
||||
};
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
@ -80,9 +80,7 @@ Parser.prototype.loadPlugins = function (plugins) {
|
||||
};
|
||||
|
||||
Parser.prototype.parse = function () {
|
||||
return new Promise((resolve) => {
|
||||
let node = this.options.program || this.startNode();
|
||||
this.nextToken();
|
||||
resolve(this.parseTopLevel(node));
|
||||
});
|
||||
return this.parseTopLevel(node);
|
||||
};
|
||||
|
||||
@ -734,7 +734,7 @@ pp.parseExportSpecifiers = function () {
|
||||
|
||||
let node = this.startNode();
|
||||
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"));
|
||||
}
|
||||
|
||||
@ -792,7 +792,7 @@ pp.parseImportSpecifiers = function (node) {
|
||||
|
||||
let specifier = this.startNode();
|
||||
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);
|
||||
node.specifiers.push(this.finishNode(specifier, "ImportSpecifier"));
|
||||
}
|
||||
|
||||
@ -128,9 +128,10 @@ pp.skipLineComment = function (startSkip) {
|
||||
++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,
|
||||
startLoc, this.curPosition());
|
||||
}
|
||||
};
|
||||
|
||||
// Called at the start of the parse and after every token. Skips
|
||||
@ -143,10 +144,12 @@ pp.skipSpace = function() {
|
||||
case 32: case 160: // ' '
|
||||
++this.pos;
|
||||
break;
|
||||
|
||||
case 13:
|
||||
if (this.input.charCodeAt(this.pos + 1) === 10) {
|
||||
++this.pos;
|
||||
}
|
||||
|
||||
case 10: case 8232: case 8233:
|
||||
++this.pos;
|
||||
if (this.options.locations) {
|
||||
@ -154,18 +157,22 @@ pp.skipSpace = function() {
|
||||
this.lineStart = this.pos;
|
||||
}
|
||||
break;
|
||||
|
||||
case 47: // '/'
|
||||
switch (this.input.charCodeAt(this.pos + 1)) {
|
||||
case 42: // '*'
|
||||
this.skipBlockComment();
|
||||
break;
|
||||
|
||||
case 47:
|
||||
this.skipLineComment(2);
|
||||
break;
|
||||
|
||||
default:
|
||||
break loop;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) {
|
||||
++this.pos;
|
||||
@ -402,28 +409,35 @@ pp.finishOp = function (type, size) {
|
||||
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,
|
||||
// since a '/' inside a '[]' set does not end the expression.
|
||||
|
||||
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;
|
||||
for (;;) {
|
||||
if (this.pos >= this.input.length) this.raise(start, "Unterminated regular expression");
|
||||
let ch = this.input.charAt(this.pos);
|
||||
if (lineBreak.test(ch)) this.raise(start, "Unterminated regular expression");
|
||||
if (!escaped) {
|
||||
if (escaped) {
|
||||
escaped = false;
|
||||
} else {
|
||||
if (ch === "[") inClass = true;
|
||||
else if (ch === "]" && inClass) inClass = false;
|
||||
else if (ch === "/" && !inClass) break;
|
||||
escaped = ch === "\\";
|
||||
} else {
|
||||
escaped = false;
|
||||
}
|
||||
++this.pos;
|
||||
}
|
||||
@ -456,23 +470,14 @@ pp.readRegexp = function () {
|
||||
}
|
||||
// Detect invalid regular expressions.
|
||||
let value = null;
|
||||
|
||||
// Rhino's regular expression parser is flaky and throws uncatchable exceptions,
|
||||
// so don't do detection if we are running under Rhino
|
||||
if (!isRhino) {
|
||||
try {
|
||||
new RegExp(tmp);
|
||||
} catch (e) {
|
||||
if (e instanceof SyntaxError) this.raise(start, `Error parsing regular expression: ${e.message}`);
|
||||
this.raise(e);
|
||||
}
|
||||
tryCreateRegexp(tmp, undefined, start);
|
||||
// Get a regular expression object for this pattern-flag pair, or `null` in
|
||||
// case the current environment doesn't support the flags it uses.
|
||||
try {
|
||||
value = new RegExp(content, mods);
|
||||
} catch (err) {}
|
||||
value = tryCreateRegexp(content, mods);
|
||||
}
|
||||
|
||||
return this.finishToken(tt.regexp, {pattern: content, flags: mods, value: value});
|
||||
};
|
||||
|
||||
|
||||
@ -27,7 +27,20 @@ function runTest(test) {
|
||||
if (expected.onToken = testOpts.onToken)
|
||||
testOpts.onToken = [];
|
||||
|
||||
return parse(test.code, testOpts).then(function (ast) {
|
||||
try {
|
||||
var ast = parse(test.code, testOpts);
|
||||
} catch (err) {
|
||||
if (test.error) {
|
||||
if (err.message === test.error) {
|
||||
return;
|
||||
} else {
|
||||
throw new Error("Expected error message: " + test.error + ". Got error message: " + err.message);
|
||||
}
|
||||
}
|
||||
|
||||
throw err;
|
||||
}
|
||||
|
||||
if (test.error) {
|
||||
throw new Error("Expected error message: " + test.error + ". But parsing succeeded.");
|
||||
} else if (test.assert) {
|
||||
@ -44,17 +57,6 @@ function runTest(test) {
|
||||
}
|
||||
if (mis) throw new Error(mis);
|
||||
}
|
||||
}, function (err) {
|
||||
if (test.error) {
|
||||
if (err.message === test.error) {
|
||||
return;
|
||||
} else {
|
||||
throw new Error("Expected error message: " + test.error + ". Got error message: " + err.message);
|
||||
}
|
||||
}
|
||||
|
||||
throw err;
|
||||
});
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
ns = fbTestFixture[ns];
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user