diff --git a/es6.js b/es6.js index 060d7a9..ab6e163 100644 --- a/es6.js +++ b/es6.js @@ -12,6 +12,8 @@ define([ //>>excludeStart('excludeBabel', pragmas.excludeBabel) var fetchText, _buildMap = {}; + // Initialise the fetchText variable with a function to download + // from a URL or to read from the file system. if (typeof window !== 'undefined' && window.navigator && window.document) { fetchText = function (url, callback) { var xhr = new XMLHttpRequest(); @@ -25,9 +27,7 @@ define([ }; xhr.send(null); }; - } else if (typeof process !== 'undefined' && - process.versions && - !!process.versions.node) { + } else { //Using special require.nodeRequire, something added by r.js. var fs = require.nodeRequire('fs'); fetchText = function (path, callback) { @@ -35,6 +35,76 @@ define([ }; } + // Detects a call to define, require or require.config functions. + function isDefineOrRequireOrRequireConfig(path) { + var expr, callee, args, arg; + + if (!path.isExpressionStatement()) return false; + + expr = path.get("expression"); + if (!expr.isCallExpression()) return false; + + args = expr.get("arguments"); + if (args.length === 0) return false; + + callee = expr.get("callee"); + // define('name', [deps], factory) + if (callee.isIdentifier({ name: "define" })) { + arg = args.shift(); + if (arg.isStringLiteral()) { + if (args.length === 0) return false; + arg = args.shift(); + } + if (arg.isArrayExpression()) { + arg = args.shift(); + return arg.isFunctionExpression() || arg.isObjectExpression(); + } + return arg.isFunctionExpression() || arg.isObjectExpression(); + } + // require([deps], success, error) + if (callee.isIdentifier({ name: "require" })) { + arg = args.shift(); + if (!arg.isArrayExpression() || args.length === 0) return false; + arg = args.shift(); + return arg.isFunctionExpression(); + } + // require.config(object) + return callee.isMemberExpression() && + callee.get('object').isIdentifier({ name: "require" }) && + callee.get('property').isIdentifier({ name: "config" }); + } + + // Thrown to abort the transpilation of an already AMD module. + function AmdDetected() {} + AmdDetected.prototype = Object.create(Error.prototype) + + // Throws if the module is an AMD module, otherwise does nothing. + function checkAmd(path) { + var body = path.get('body'); + var length = body.length; + var i, node; + for (i = 0; i < length; ++i) { + node = body[i]; + // If import or export is detected, transform right away. + if (node.isImportDeclaration() || + node.isExportDeclaration()) break; + // If define or require is detected, abort right away. + if (isDefineOrRequireOrRequireConfig(node)) { + throw new AmdDetected(); + } + } + } + + // Throws if the module is an AMD module, otherwise does nothing. + function amdChecker() { + return { + visitor: { + Program: { enter: checkAmd } + } + }; + } + + babel.registerPlugin('amd-checker', amdChecker); babel.registerPlugin('module-resolver', moduleResolver); function resolvePath (sourcePath) { @@ -47,6 +117,7 @@ define([ var fileExtension = pluginOptions.fileExtension || '.js'; var defaultOptions = { plugins: (pluginOptions.extraPlugins || []).concat([ + 'amd-checker', 'transform-modules-amd', [ 'module-resolver', @@ -85,7 +156,10 @@ return { try { code = babel.transform(text, options).code; } catch (error) { - return onload.error(error); + if (!(error instanceof AmdDetected)) { + return onload.error(error); + } + code = text; } if (config.isBuild) {