[react-packager] `System.import` transform

This commit is contained in:
Martín Bigio 2015-08-27 09:33:59 -07:00
parent 8ec1a180df
commit 5dbde93ec6
2 changed files with 136 additions and 0 deletions

View File

@ -0,0 +1,71 @@
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*
* @emails oncall+jsinfra
*/
'use strict';
jest.autoMockOff();
jest.mock('../../../BundlesLayout');
const babel = require('babel-core');
const BundlesLayout = require('../../../BundlesLayout');
const testData = {
isolated: {
input: 'System.import("moduleA");',
output: 'loadBundles(["bundle.0"]);'
},
single: {
input: 'System.import("moduleA").then(function (bundleA) {});',
output: 'loadBundles(["bundle.0"]).then(function (bundleA) {});'
},
multiple: {
input: [
'Promise.all([',
'System.import("moduleA"), System.import("moduleB"),',
']).then(function (bundlesA, bundlesB) {});',
].join('\n'),
output: [
'Promise.all([',
'loadBundles(["bundle.0"]), loadBundles(["bundle.1"])',
']).then(function (bundlesA, bundlesB) {});',
].join(''),
},
};
describe('System.import', () => {
let layout = new BundlesLayout();
BundlesLayout.prototype.getBundleIDForModule.mockImpl(module => {
switch (module) {
case 'moduleA': return 'bundle.0';
case 'moduleB': return 'bundle.1';
}
});
function transform(source) {
return babel.transform(source, {
plugins: [require('../')],
blacklist: ['strict'],
extra: { bundlesLayout: layout },
}).code;
}
function test(data) {
// transform and remove new lines
expect(transform(data.input).replace(/(\r\n|\n|\r)/gm,'')).toEqual(data.output);
}
it('should transform isolated `System.import`', () => {
test(testData.isolated);
});
it('should transform single `System.import`', () => {
test(testData.single);
});
it('should transform multiple `System.import`s', () => {
test(testData.multiple);
});
});

View File

@ -0,0 +1,65 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/
/*jslint node: true */
'use strict';
var t = require('babel-core').types;
/**
* Transforms asynchronous module importing into a function call
* that includes which bundle needs to be loaded
*
* Transforms:
*
* System.import('moduleA')
*
* to:
*
* loadBundles('bundleA')
*/
module.exports = function systemImportTransform(babel) {
return new babel.Transformer('system-import', {
CallExpression: function(node, parent, scope, state) {
if (!isAppropriateSystemImportCall(node, parent)) {
return node;
}
var bundlesLayout = state.opts.extra.bundlesLayout;
var bundleID = bundlesLayout.getBundleIDForModule(
node.arguments[0].value
);
var bundles = bundleID.split('.');
bundles.splice(0, 1);
bundles = bundles.map(function(id) {
return t.literal('bundle.' + id);
});
return t.callExpression(
t.identifier('loadBundles'),
[t.arrayExpression(bundles)]
);
},
metadata: {
group: 'fb'
}
});
};
function isAppropriateSystemImportCall(node) {
return (
node.callee.type === 'MemberExpression' &&
node.callee.object.name === 'System' &&
node.callee.property.name === 'import' &&
node.arguments.length === 1 &&
node.arguments[0].type === 'Literal'
);
}