diff --git a/react-packager/src/Bundler/index.js b/react-packager/src/Bundler/index.js index a07d73f7..99923e65 100644 --- a/react-packager/src/Bundler/index.js +++ b/react-packager/src/Bundler/index.js @@ -13,7 +13,6 @@ const fs = require('fs'); const path = require('path'); const Promise = require('promise'); const ProgressBar = require('progress'); -const BundlesLayout = require('../BundlesLayout'); const Cache = require('../DependencyResolver/Cache'); const Transformer = require('../JSTransformer'); const Resolver = require('../Resolver'); @@ -126,13 +125,6 @@ class Bundler { cache: this._cache, }); - this._bundlesLayout = new BundlesLayout({ - dependencyResolver: this._resolver, - resetCache: opts.resetCache, - cacheVersion: opts.cacheVersion, - projectRoots: opts.projectRoots, - }); - this._transformer = new Transformer({ projectRoots: opts.projectRoots, blacklistRE: opts.blacklistRE, @@ -156,10 +148,6 @@ class Bundler { return this._cache.end(); } - getLayout(main, isDev) { - return this._bundlesLayout.generateLayout(main, isDev); - } - bundle(options) { const {dev, isUnbundle, platform} = options; const moduleSystemDeps = diff --git a/react-packager/src/BundlesLayout/__tests__/BundlesLayout-test.js b/react-packager/src/BundlesLayout/__tests__/BundlesLayout-test.js deleted file mode 100644 index dafdb368..00000000 --- a/react-packager/src/BundlesLayout/__tests__/BundlesLayout-test.js +++ /dev/null @@ -1,320 +0,0 @@ -/** - * 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. - */ -'use strict'; - -jest.dontMock('../index') - .mock('fs'); - -var Promise = require('promise'); -var BundlesLayout = require('../index'); -var Resolver = require('../../Resolver'); -var loadCacheSync = require('../../DependencyResolver/Cache/lib/loadCacheSync'); - -describe('BundlesLayout', () => { - function newBundlesLayout(options) { - return new BundlesLayout(Object.assign({ - projectRoots: ['/root'], - dependencyResolver: new Resolver(), - }, options)); - } - - describe('layout', () => { - function isPolyfill() { - return false; - } - - describe('getLayout', () => { - function dep(path) { - return { - path: path, - isPolyfill: isPolyfill, - }; - } - - pit('should bundle sync dependencies', () => { - Resolver.prototype.getDependencies.mockImpl((path) => { - switch (path) { - case '/root/index.js': - return Promise.resolve({ - dependencies: [dep('/root/index.js'), dep('/root/a.js')], - asyncDependencies: [], - }); - case '/root/a.js': - return Promise.resolve({ - dependencies: [dep('/root/a.js')], - asyncDependencies: [], - }); - default: - throw 'Undefined path: ' + path; - } - }); - - return newBundlesLayout({resetCache: true}) - .getLayout('/root/index.js') - .then(bundles => - expect(bundles).toEqual({ - id: 'bundle.0', - modules: ['/root/index.js', '/root/a.js'], - children: [], - }) - ); - }); - - pit('should separate async dependencies into different bundle', () => { - Resolver.prototype.getDependencies.mockImpl((path) => { - switch (path) { - case '/root/index.js': - return Promise.resolve({ - dependencies: [dep('/root/index.js')], - asyncDependencies: [['/root/a.js']], - }); - case '/root/a.js': - return Promise.resolve({ - dependencies: [dep('/root/a.js')], - asyncDependencies: [], - }); - default: - throw 'Undefined path: ' + path; - } - }); - - return newBundlesLayout({resetCache: true}) - .getLayout('/root/index.js') - .then(bundles => - expect(bundles).toEqual({ - id: 'bundle.0', - modules: ['/root/index.js'], - children: [{ - id:'bundle.0.1', - modules: ['/root/a.js'], - children: [], - }], - }) - ); - }); - - pit('separate async dependencies of async dependencies', () => { - Resolver.prototype.getDependencies.mockImpl((path) => { - switch (path) { - case '/root/index.js': - return Promise.resolve({ - dependencies: [dep('/root/index.js')], - asyncDependencies: [['/root/a.js']], - }); - case '/root/a.js': - return Promise.resolve({ - dependencies: [dep('/root/a.js')], - asyncDependencies: [['/root/b.js']], - }); - case '/root/b.js': - return Promise.resolve({ - dependencies: [dep('/root/b.js')], - asyncDependencies: [], - }); - default: - throw 'Undefined path: ' + path; - } - }); - - return newBundlesLayout({resetCache: true}) - .getLayout('/root/index.js') - .then(bundles => - expect(bundles).toEqual({ - id: 'bundle.0', - modules: ['/root/index.js'], - children: [{ - id: 'bundle.0.1', - modules: ['/root/a.js'], - children: [{ - id: 'bundle.0.1.2', - modules: ['/root/b.js'], - children: [], - }], - }], - }) - ); - }); - - pit('separate bundle sync dependencies of async ones on same bundle', () => { - Resolver.prototype.getDependencies.mockImpl((path) => { - switch (path) { - case '/root/index.js': - return Promise.resolve({ - dependencies: [dep('/root/index.js')], - asyncDependencies: [['/root/a.js']], - }); - case '/root/a.js': - return Promise.resolve({ - dependencies: [dep('/root/a.js'), dep('/root/b.js')], - asyncDependencies: [], - }); - case '/root/b.js': - return Promise.resolve({ - dependencies: [dep('/root/b.js')], - asyncDependencies: [], - }); - default: - throw 'Undefined path: ' + path; - } - }); - - return newBundlesLayout({resetCache: true}) - .getLayout('/root/index.js') - .then(bundles => - expect(bundles).toEqual({ - id: 'bundle.0', - modules: ['/root/index.js'], - children: [{ - id: 'bundle.0.1', - modules: ['/root/a.js', '/root/b.js'], - children: [], - }], - }) - ); - }); - - pit('separate cache in which bundle is each dependency', () => { - Resolver.prototype.getDependencies.mockImpl((path) => { - switch (path) { - case '/root/index.js': - return Promise.resolve({ - dependencies: [dep('/root/index.js'), dep('/root/a.js')], - asyncDependencies: [], - }); - case '/root/a.js': - return Promise.resolve({ - dependencies: [dep('/root/a.js')], - asyncDependencies: [['/root/b.js']], - }); - case '/root/b.js': - return Promise.resolve({ - dependencies: [dep('/root/b.js')], - asyncDependencies: [], - }); - default: - throw 'Undefined path: ' + path; - } - }); - - return newBundlesLayout({resetCache: true}) - .getLayout('/root/index.js') - .then(bundles => - expect(bundles).toEqual({ - id: 'bundle.0', - modules: ['/root/index.js', '/root/a.js'], - children: [{ - id: 'bundle.0.1', - modules: ['/root/b.js'], - children: [], - }], - }) - ); - }); - - pit('separate cache in which bundle is each dependency', () => { - Resolver.prototype.getDependencies.mockImpl((path) => { - switch (path) { - case '/root/index.js': - return Promise.resolve({ - dependencies: [dep('/root/index.js'), dep('/root/a.js')], - asyncDependencies: [['/root/b.js'], ['/root/c.js']], - }); - case '/root/a.js': - return Promise.resolve({ - dependencies: [dep('/root/a.js')], - asyncDependencies: [], - }); - case '/root/b.js': - return Promise.resolve({ - dependencies: [dep('/root/b.js')], - asyncDependencies: [['/root/d.js']], - }); - case '/root/c.js': - return Promise.resolve({ - dependencies: [dep('/root/c.js')], - asyncDependencies: [], - }); - case '/root/d.js': - return Promise.resolve({ - dependencies: [dep('/root/d.js')], - asyncDependencies: [], - }); - default: - throw 'Undefined path: ' + path; - } - }); - - var layout = newBundlesLayout({resetCache: true}); - return layout.getLayout('/root/index.js').then(() => { - expect(layout.getBundleIDForModule('/root/index.js')).toBe('bundle.0'); - expect(layout.getBundleIDForModule('/root/a.js')).toBe('bundle.0'); - expect(layout.getBundleIDForModule('/root/b.js')).toBe('bundle.0.1'); - expect(layout.getBundleIDForModule('/root/c.js')).toBe('bundle.0.2'); - expect(layout.getBundleIDForModule('/root/d.js')).toBe('bundle.0.1.3'); - }); - }); - }); - }); - - describe('cache', () => { - beforeEach(() => { - loadCacheSync.mockReturnValue({ - '/root/index.js': { - id: 'bundle.0', - modules: ['/root/index.js'], - children: [{ - id: 'bundle.0.1', - modules: ['/root/a.js'], - children: [], - }], - }, - '/root/b.js': { - id: 'bundle.2', - modules: ['/root/b.js'], - children: [], - }, - }); - }); - - pit('should load layouts', () => { - const layout = newBundlesLayout({ resetCache: false }); - - return Promise - .all([ - layout.getLayout('/root/index.js'), - layout.getLayout('/root/b.js'), - ]) - .then(([layoutIndex, layoutB]) => { - expect(layoutIndex).toEqual({ - id: 'bundle.0', - modules: ['/root/index.js'], - children: [{ - id: 'bundle.0.1', - modules: ['/root/a.js'], - children: [], - }], - }); - - expect(layoutB).toEqual({ - id: 'bundle.2', - modules: ['/root/b.js'], - children: [], - }); - }); - }); - - it('should load moduleToBundle map', () => { - const layout = newBundlesLayout({ resetCache: false }); - - expect(layout.getBundleIDForModule('/root/index.js')).toBe('bundle.0'); - expect(layout.getBundleIDForModule('/root/a.js')).toBe('bundle.0.1'); - expect(layout.getBundleIDForModule('/root/b.js')).toBe('bundle.2'); - }); - }); -}); diff --git a/react-packager/src/BundlesLayout/__tests__/BundlesLayoutIntegration-test.js b/react-packager/src/BundlesLayout/__tests__/BundlesLayoutIntegration-test.js deleted file mode 100644 index 00868b22..00000000 --- a/react-packager/src/BundlesLayout/__tests__/BundlesLayoutIntegration-test.js +++ /dev/null @@ -1,599 +0,0 @@ -/** - * 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. - */ -'use strict'; - -jest - .autoMockOff() - .mock('../../DependencyResolver/Cache') - .mock('../../Activity'); - -const Promise = require('promise'); -const path = require('path'); - -jest.mock('fs'); - -var BundlesLayout = require('../index'); -var Cache = require('../../DependencyResolver/Cache'); -var Resolver = require('../../Resolver'); -var fs = require('fs'); - -describe('BundlesLayout', () => { - var fileWatcher; - - const polyfills = [ - 'polyfills/prelude_dev.js', - 'polyfills/prelude.js', - 'polyfills/require.js', - 'polyfills/polyfills.js', - 'polyfills/console.js', - 'polyfills/error-guard.js', - 'polyfills/String.prototype.es6.js', - 'polyfills/Array.prototype.es6.js', - 'polyfills/Array.es6.js', - 'polyfills/Object.es7.js', - 'polyfills/babelHelpers.js', - ]; - const baseFs = getBaseFs(); - - beforeEach(() => { - fileWatcher = { - on: () => this, - isWatchman: () => Promise.resolve(false) - }; - }); - - describe('generate', () => { - function newBundlesLayout() { - const resolver = new Resolver({ - projectRoots: ['/root', '/' + __dirname.split('/')[1]], - fileWatcher: fileWatcher, - cache: new Cache(), - assetExts: ['js', 'png'], - assetRoots: ['/root'], - }); - - return new BundlesLayout({ - dependencyResolver: resolver, - resetCache: true, - projectRoots: ['/root', '/' + __dirname.split('/')[1]], - }); - } - - function stripPolyfills(bundle) { - return Promise - .all(bundle.children.map(childModule => stripPolyfills(childModule))) - .then(children => { - const modules = bundle.modules - .filter(moduleName => { // filter polyfills - for (let p of polyfills) { - if (moduleName.indexOf(p) !== -1) { - return false; - } - } - return true; - }); - - return { - id: bundle.id, - modules: modules, - children: children, - }; - }); - } - - function setMockFilesystem(mockFs) { - fs.__setMockFilesystem(Object.assign(mockFs, baseFs)); - } - - pit('should bundle single-module app', () => { - setMockFilesystem({ - 'root': { - 'index.js': ` - /** - * @providesModule xindex - */`, - } - }); - - return newBundlesLayout().getLayout('/root/index.js').then(bundles => - stripPolyfills(bundles).then(resolvedBundles => - expect(resolvedBundles).toEqual({ - id: 'bundle.0', - modules: ['/root/index.js'], - children: [], - }) - ) - ); - }); - - pit('should bundle dependant modules', () => { - setMockFilesystem({ - 'root': { - 'index.js': ` - /** - * @providesModule xindex - */ - require("xa");`, - 'a.js': ` - /** - * @providesModule xa - */`, - } - }); - - return newBundlesLayout().getLayout('/root/index.js').then(bundles => - stripPolyfills(bundles).then(resolvedBundles => - expect(resolvedBundles).toEqual({ - id: 'bundle.0', - modules: ['/root/index.js', '/root/a.js'], - children: [], - }) - ) - ); - }); - - pit('should split bundles for async dependencies', () => { - setMockFilesystem({ - 'root': { - 'index.js': ` - /** - * @providesModule xindex - */ - ${'System.import'}("xa");`, - 'a.js': ` - /**, - * @providesModule xa - */`, - } - }); - - return newBundlesLayout().getLayout('/root/index.js').then(bundles => - stripPolyfills(bundles).then(resolvedBundles => - expect(resolvedBundles).toEqual({ - id: 'bundle.0', - modules: ['/root/index.js'], - children: [{ - id: 'bundle.0.1', - modules: ['/root/a.js'], - children: [], - }], - }) - ) - ); - }); - - pit('should split into multiple bundles separate async dependencies', () => { - setMockFilesystem({ - 'root': { - 'index.js': ` - /** - * @providesModule xindex - */ - ${'System.import'}("xa"); - ${'System.import'}("xb");`, - 'a.js': ` - /**, - * @providesModule xa - */`, - 'b.js': ` - /** - * @providesModule xb - */`, - } - }); - - return newBundlesLayout().getLayout('/root/index.js').then(bundles => - stripPolyfills(bundles).then(resolvedBundles => - expect(resolvedBundles).toEqual({ - id: 'bundle.0', - modules: ['/root/index.js'], - children: [ - { - id: 'bundle.0.1', - modules: ['/root/a.js'], - children: [], - }, { - id: 'bundle.0.2', - modules: ['/root/b.js'], - children: [], - }, - ], - }) - ) - ); - }); - - pit('should fully traverse sync dependencies', () => { - setMockFilesystem({ - 'root': { - 'index.js': ` - /** - * @providesModule xindex - */ - require("xa"); - ${'System.import'}("xb");`, - 'a.js': ` - /**, - * @providesModule xa - */`, - 'b.js': ` - /** - * @providesModule xb - */`, - } - }); - - return newBundlesLayout().getLayout('/root/index.js').then(bundles => - stripPolyfills(bundles).then(resolvedBundles => - expect(resolvedBundles).toEqual({ - id: 'bundle.0', - modules: ['/root/index.js', '/root/a.js'], - children: [{ - id: 'bundle.0.1', - modules: ['/root/b.js'], - children: [], - }], - }) - ) - ); - }); - - pit('should include sync dependencies async dependencies might have', () => { - setMockFilesystem({ - 'root': { - 'index.js': ` - /** - * @providesModule xindex - */ - ${'System.import'}("xa");`, - 'a.js': ` - /**, - * @providesModule xa - */, - require("xb");`, - 'b.js': ` - /** - * @providesModule xb - */ - require("xc");`, - 'c.js': ` - /** - * @providesModule xc - */`, - } - }); - - return newBundlesLayout().getLayout('/root/index.js').then(bundles => - stripPolyfills(bundles).then(resolvedBundles => - expect(resolvedBundles).toEqual({ - id: 'bundle.0', - modules: ['/root/index.js'], - children: [{ - id: 'bundle.0.1', - modules: ['/root/a.js', '/root/b.js', '/root/c.js'], - children: [], - }], - }) - ) - ); - }); - - pit('should allow duplicated dependencies across bundles', () => { - setMockFilesystem({ - 'root': { - 'index.js': ` - /** - * @providesModule xindex - */ - ${'System.import'}("xa"); - ${'System.import'}("xb");`, - 'a.js': ` - /**, - * @providesModule xa - */, - require("xc");`, - 'b.js': ` - /** - * @providesModule xb - */ - require("xc");`, - 'c.js': ` - /** - * @providesModule xc - */`, - } - }); - - return newBundlesLayout().getLayout('/root/index.js').then(bundles => - stripPolyfills(bundles).then(resolvedBundles => - expect(resolvedBundles).toEqual({ - id: 'bundle.0', - modules: ['/root/index.js'], - children: [ - { - id: 'bundle.0.1', - modules: ['/root/a.js', '/root/c.js'], - children: [], - }, - { - id: 'bundle.0.2', - modules: ['/root/b.js', '/root/c.js'], - children: [], - }, - ], - }) - ) - ); - }); - - pit('should put in separate bundles async dependencies of async dependencies', () => { - setMockFilesystem({ - 'root': { - 'index.js': ` - /** - * @providesModule xindex - */ - ${'System.import'}("xa");`, - 'a.js': ` - /**, - * @providesModule xa - */, - ${'System.import'}("xb");`, - 'b.js': ` - /** - * @providesModule xb - */ - require("xc");`, - 'c.js': ` - /** - * @providesModule xc - */`, - } - }); - - return newBundlesLayout().getLayout('/root/index.js').then(bundles => - stripPolyfills(bundles).then(resolvedBundles => - expect(resolvedBundles).toEqual({ - id: 'bundle.0', - modules: ['/root/index.js'], - children: [ - { - id: 'bundle.0.1', - modules: ['/root/a.js'], - children: [{ - id: 'bundle.0.1.2', - modules: ['/root/b.js', '/root/c.js'], - children: [], - }], - }, - ], - }) - ) - ); - }); - - pit('should put image dependencies into separate bundles', () => { - setMockFilesystem({ - 'root': { - 'index.js': ` - /** - * @providesModule xindex - */ - ${'System.import'}("xa");`, - 'a.js':` - /**, - * @providesModule xa - */, - require("./img.png");`, - 'img.png': '', - } - }); - - return newBundlesLayout().getLayout('/root/index.js').then(bundles => - stripPolyfills(bundles).then(resolvedBundles => - expect(resolvedBundles).toEqual({ - id: 'bundle.0', - modules: ['/root/index.js'], - children: [{ - id: 'bundle.0.1', - modules: ['/root/a.js', '/root/img.png'], - children: [], - }], - }) - ) - ); - }); - - pit('should put image dependencies across bundles', () => { - setMockFilesystem({ - 'root': { - 'index.js': ` - /** - * @providesModule xindex - */ - ${'System.import'}("xa"); - ${'System.import'}("xb");`, - 'a.js':` - /**, - * @providesModule xa - */, - require("./img.png");`, - 'b.js':` - /**, - * @providesModule xb - */, - require("./img.png");`, - 'img.png': '', - } - }); - - return newBundlesLayout().getLayout('/root/index.js').then(bundles => - stripPolyfills(bundles).then(resolvedBundles => - expect(resolvedBundles).toEqual({ - id: 'bundle.0', - modules: ['/root/index.js'], - children: [ - { - id: 'bundle.0.1', - modules: ['/root/a.js', '/root/img.png'], - children: [], - }, - { - id: 'bundle.0.2', - modules: ['/root/b.js', '/root/img.png'], - children: [], - }, - ], - }) - ) - ); - }); - - pit('could async require asset', () => { - setMockFilesystem({ - 'root': { - 'index.js': ` - /** - * @providesModule xindex - */ - ${'System.import'}("./img.png");`, - 'img.png': '', - } - }); - - return newBundlesLayout().getLayout('/root/index.js').then(bundles => - stripPolyfills(bundles).then(resolvedBundles => - expect(resolvedBundles).toEqual({ - id: 'bundle.0', - modules: ['/root/index.js'], - children: [{ - id: 'bundle.0.1', - modules: ['/root/img.png'], - children: [], - }], - }) - ) - ); - }); - - pit('should include deprecated assets into separate bundles', () => { - setMockFilesystem({ - 'root': { - 'index.js': ` - /** - * @providesModule xindex - */ - ${'System.import'}("xa");`, - 'a.js':` - /**, - * @providesModule xa - */, - require("image!img");`, - 'img.png': '', - } - }); - - return newBundlesLayout().getLayout('/root/index.js').then(bundles => - stripPolyfills(bundles).then(resolvedBundles => - expect(resolvedBundles).toEqual({ - id: 'bundle.0', - modules: ['/root/index.js'], - children: [{ - id: 'bundle.0.1', - modules: ['/root/a.js', '/root/img.png'], - children: [], - }], - }) - ) - ); - }); - - pit('could async require deprecated asset', () => { - setMockFilesystem({ - 'root': { - 'index.js': ` - /** - * @providesModule xindex - */ - ${'System.import'}("image!img");`, - 'img.png': '', - } - }); - - return newBundlesLayout().getLayout('/root/index.js').then(bundles => - stripPolyfills(bundles).then(resolvedBundles => - expect(resolvedBundles).toEqual({ - id: 'bundle.0', - modules: ['/root/index.js'], - children: [{ - id: 'bundle.0.1', - modules: ['/root/img.png'], - children: [], - }], - }) - ) - ); - }); - - pit('should put packages into bundles', () => { - setMockFilesystem({ - 'root': { - 'index.js': ` - /** - * @providesModule xindex - */ - ${'System.import'}("aPackage");`, - 'aPackage': { - 'package.json': JSON.stringify({ - name: 'aPackage', - main: './main.js', - browser: { - './main.js': './client.js', - }, - }), - 'main.js': 'some other code', - 'client.js': 'some code', - }, - } - }); - - return newBundlesLayout().getLayout('/root/index.js').then(bundles => - stripPolyfills(bundles).then(resolvedBundles => - expect(resolvedBundles).toEqual({ - id: 'bundle.0', - modules: ['/root/index.js'], - children: [{ - id: 'bundle.0.1', - modules: ['/root/aPackage/client.js'], - children: [], - }], - }) - ) - ); - }); - }); - - function getBaseFs() { - const p = path.join(__dirname, '../../../Resolver/polyfills').substring(1); - const root = {}; - let currentPath = root; - - p.split('/').forEach(part => { - const child = {}; - currentPath[part] = child; - currentPath = child; - }); - - polyfills.forEach(polyfill => - currentPath[polyfill.split('/')[1]] = '' - ); - - return root; - } -}); diff --git a/react-packager/src/BundlesLayout/index.js b/react-packager/src/BundlesLayout/index.js deleted file mode 100644 index 2fd90623..00000000 --- a/react-packager/src/BundlesLayout/index.js +++ /dev/null @@ -1,219 +0,0 @@ -/** - * 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. - */ -'use strict'; - -const Activity = require('../Activity'); - -const _ = require('underscore'); -const declareOpts = require('../lib/declareOpts'); -const fs = require('fs'); -const getCacheFilePath = require('../DependencyResolver/Cache/lib/getCacheFilePath'); -const loadCacheSync = require('../DependencyResolver/Cache/lib/loadCacheSync'); -const version = require('../../../../package.json').version; -const path = require('path'); -const tmpdir = require('os').tmpDir(); - -const validateOpts = declareOpts({ - dependencyResolver: { - type: 'object', - required: true, - }, - resetCache: { - type: 'boolean', - default: false, - }, - cacheVersion: { - type: 'string', - default: '1.0', - }, - projectRoots: { - type: 'array', - required: true, - }, -}); - -const BUNDLE_PREFIX = 'bundle'; - -/** - * Class that takes care of separating the graph of dependencies into - * separate bundles - */ -class BundlesLayout { - constructor(options) { - const opts = validateOpts(options); - this._resolver = opts.dependencyResolver; - - // Cache in which bundle is each module. - this._moduleToBundle = Object.create(null); - - // Cache the bundles layouts for each entry point. This entries - // are not evicted unless the user explicitly specifies so as - // computing them is pretty expensive - this._layouts = Object.create(null); - - // TODO: watch for file creations and removals to update this caches - - this._cacheFilePath = this._getCacheFilePath(opts); - if (!opts.resetCache) { - this._loadCacheSync(this._cacheFilePath); - } else { - this._persistCacheEventually(); - } - } - - getLayout(entryPath, isDev) { - if (this._layouts[entryPath]) { - return this._layouts[entryPath]; - } - var currentBundleID = 0; - const rootBundle = { - id: BUNDLE_PREFIX + '.' + currentBundleID++, - modules: [], - children: [], - }; - var pending = [{paths: [entryPath], bundle: rootBundle}]; - - this._layouts[entryPath] = promiseWhile( - () => pending.length > 0, - () => rootBundle, - () => { - const {paths, bundle} = pending.shift(); - - // pending sync dependencies we still need to explore for the current - // pending dependency - const pendingSyncDeps = paths; - - // accum variable for sync dependencies of the current pending - // dependency we're processing - const syncDependencies = Object.create(null); - - return promiseWhile( - () => pendingSyncDeps.length > 0, - () => { - const dependencies = Object.keys(syncDependencies); - if (dependencies.length > 0) { - bundle.modules = dependencies; - } - - // persist changes to layouts - this._persistCacheEventually(); - }, - index => { - const pendingSyncDep = pendingSyncDeps.shift(); - return this._resolver - .getDependencies(pendingSyncDep, {dev: isDev}) - .then(deps => { - deps.dependencies.forEach(dep => { - if (dep.path !== pendingSyncDep && !dep.isPolyfill()) { - pendingSyncDeps.push(dep.path); - } - syncDependencies[dep.path] = true; - this._moduleToBundle[dep.path] = bundle.id; - }); - deps.asyncDependencies.forEach(asyncDeps => { - const childBundle = { - id: bundle.id + '.' + currentBundleID++, - modules: [], - children: [], - }; - - bundle.children.push(childBundle); - pending.push({paths: asyncDeps, bundle: childBundle}); - }); - }); - }, - ); - }, - ); - - return this._layouts[entryPath]; - } - - getBundleIDForModule(path) { - return this._moduleToBundle[path]; - } - - _loadCacheSync(cachePath) { - const loadCacheId = Activity.startEvent('Loading bundles layout'); - const cacheOnDisk = loadCacheSync(cachePath); - - // TODO: create single-module bundles for unexistent modules - // TODO: remove modules that no longer exist - Object.keys(cacheOnDisk).forEach(entryPath => { - this._layouts[entryPath] = Promise.resolve(cacheOnDisk[entryPath]); - this._fillModuleToBundleMap(cacheOnDisk[entryPath]); - }); - - Activity.endEvent(loadCacheId); - } - - _fillModuleToBundleMap(bundle) { - bundle.modules.forEach(module => this._moduleToBundle[module] = bundle.id); - bundle.children.forEach(child => this._fillModuleToBundleMap(child)); - } - - _persistCacheEventually() { - _.debounce( - this._persistCache.bind(this), - 2000, - ); - } - - _persistCache() { - if (this._persisting !== null) { - return this._persisting; - } - - this._persisting = Promise - .all(_.values(this._layouts)) - .then(bundlesLayout => { - var json = Object.create(null); - Object.keys(this._layouts).forEach((p, i) => - json[p] = bundlesLayout[i] - ); - - return Promise.denodeify(fs.writeFile)( - this._cacheFilepath, - JSON.stringify(json), - ); - }) - .then(() => this._persisting = null); - - return this._persisting; - } - - _getCacheFilePath(options) { - return getCacheFilePath( - tmpdir, - 'react-packager-bundles-cache-', - version, - options.projectRoots.join(',').split(path.sep).join('-'), - options.cacheVersion || '0', - ); - } -} - -// Runs the body Promise meanwhile the condition callback is satisfied. -// Once it's not satisfied anymore, it returns what the results callback -// indicates -function promiseWhile(condition, result, body) { - return _promiseWhile(condition, result, body, 0); -} - -function _promiseWhile(condition, result, body, index) { - if (!condition()) { - return Promise.resolve(result()); - } - - return body(index).then(() => - _promiseWhile(condition, result, body, index + 1) - ); -} - -module.exports = BundlesLayout; diff --git a/react-packager/src/DependencyResolver/AssetModule.js b/react-packager/src/DependencyResolver/AssetModule.js index f5555fac..c2f51fbb 100644 --- a/react-packager/src/DependencyResolver/AssetModule.js +++ b/react-packager/src/DependencyResolver/AssetModule.js @@ -21,10 +21,6 @@ class AssetModule extends Module { return Promise.resolve([]); } - getAsyncDependencies() { - return Promise.resolve([]); - } - read() { return Promise.resolve({}); } diff --git a/react-packager/src/DependencyResolver/AssetModule_DEPRECATED.js b/react-packager/src/DependencyResolver/AssetModule_DEPRECATED.js index a77d0aef..3c465946 100644 --- a/react-packager/src/DependencyResolver/AssetModule_DEPRECATED.js +++ b/react-packager/src/DependencyResolver/AssetModule_DEPRECATED.js @@ -24,10 +24,6 @@ class AssetModule_DEPRECATED extends Module { return Promise.resolve([]); } - getAsyncDependencies() { - return Promise.resolve([]); - } - hash() { return `AssetModule_DEPRECATED : ${this.path}`; } diff --git a/react-packager/src/DependencyResolver/DependencyGraph/ResolutionRequest.js b/react-packager/src/DependencyResolver/DependencyGraph/ResolutionRequest.js index 879c53ef..c4004ed7 100644 --- a/react-packager/src/DependencyResolver/DependencyGraph/ResolutionRequest.js +++ b/react-packager/src/DependencyResolver/DependencyGraph/ResolutionRequest.js @@ -187,23 +187,6 @@ class ResolutionRequest { }); } - getAsyncDependencies(response) { - return Promise.resolve().then(() => { - const mod = this._moduleCache.getModule(this._entryPath); - return mod.getAsyncDependencies().then(bundles => - Promise - .all(bundles.map(bundle => - Promise.all(bundle.map( - dep => this.resolveDependency(mod, dep) - )) - )) - .then(bs => bs.map(bundle => bundle.map(dep => dep.path))) - ); - }).then(asyncDependencies => asyncDependencies.forEach( - (dependency) => response.pushAsyncDependency(dependency) - )); - } - _getAllMocks(pattern) { // Take all mocks in all the roots into account. This is necessary // because currently mocks are global: any module can be mocked by diff --git a/react-packager/src/DependencyResolver/DependencyGraph/ResolutionResponse.js b/react-packager/src/DependencyResolver/DependencyGraph/ResolutionResponse.js index c13895fb..56e1ed7a 100644 --- a/react-packager/src/DependencyResolver/DependencyGraph/ResolutionResponse.js +++ b/react-packager/src/DependencyResolver/DependencyGraph/ResolutionResponse.js @@ -11,7 +11,6 @@ class ResolutionResponse { constructor() { this.dependencies = []; - this.asyncDependencies = []; this.mainModuleId = null; this.mocks = null; this.numPrependedDependencies = 0; @@ -22,13 +21,11 @@ class ResolutionResponse { copy(properties) { const { dependencies = this.dependencies, - asyncDependencies = this.asyncDependencies, mainModuleId = this.mainModuleId, mocks = this.mocks, } = properties; return Object.assign(new this.constructor(), this, { dependencies, - asyncDependencies, mainModuleId, mocks, }); @@ -69,11 +66,6 @@ class ResolutionResponse { this.numPrependedDependencies += 1; } - pushAsyncDependency(dependency) { - this._assertNotFinalized(); - this.asyncDependencies.push(dependency); - } - setResolvedDependencyPairs(module, pairs) { this._assertNotFinalized(); const hash = module.hash(); diff --git a/react-packager/src/DependencyResolver/DependencyGraph/__tests__/DependencyGraph-test.js b/react-packager/src/DependencyResolver/DependencyGraph/__tests__/DependencyGraph-test.js index 09a44543..990e234f 100644 --- a/react-packager/src/DependencyResolver/DependencyGraph/__tests__/DependencyGraph-test.js +++ b/react-packager/src/DependencyResolver/DependencyGraph/__tests__/DependencyGraph-test.js @@ -4068,40 +4068,6 @@ describe('DependencyGraph', function() { }); }); - describe('getAsyncDependencies', () => { - pit('should get dependencies', function() { - var root = '/root'; - fs.__setMockFilesystem({ - 'root': { - 'index.js': [ - '/**', - ' * @providesModule index', - ' */', - 'System.' + 'import("a")', - ].join('\n'), - 'a.js': [ - '/**', - ' * @providesModule a', - ' */', - ].join('\n'), - }, - }); - - var dgraph = new DependencyGraph({ - ...defaults, - roots: [root], - }); - - return dgraph.getDependencies('/root/index.js') - .then(response => response.finalize()) - .then(({ asyncDependencies }) => { - expect(asyncDependencies).toEqual([ - ['/root/a.js'], - ]); - }); - }); - }); - describe('Extensions', () => { pit('supports custom file extensions', () => { var root = '/root'; diff --git a/react-packager/src/DependencyResolver/DependencyGraph/index.js b/react-packager/src/DependencyResolver/DependencyGraph/index.js index 3c5ade66..9241b18a 100644 --- a/react-packager/src/DependencyResolver/DependencyGraph/index.js +++ b/react-packager/src/DependencyResolver/DependencyGraph/index.js @@ -185,14 +185,11 @@ class DependencyGraph { const response = new ResolutionResponse(); - return Promise.all([ - req.getOrderedDependencies( - response, - this._opts.mocksPattern, - recursive, - ), - req.getAsyncDependencies(response), - ]).then(() => response); + return req.getOrderedDependencies( + response, + this._opts.mocksPattern, + recursive, + ).then(() => response); }); } diff --git a/react-packager/src/DependencyResolver/Module.js b/react-packager/src/DependencyResolver/Module.js index f9142611..116a52e0 100644 --- a/react-packager/src/DependencyResolver/Module.js +++ b/react-packager/src/DependencyResolver/Module.js @@ -91,14 +91,6 @@ class Module { ); } - getAsyncDependencies() { - return this._cache.get( - this.path, - 'asyncDependencies', - () => this.read().then(data => data.asyncDependencies) - ); - } - invalidate() { this._cache.invalidate(this.path); } @@ -146,7 +138,6 @@ class Module { return { id, dependencies: [], - asyncDependencies: [], code: content, }; } else { @@ -155,13 +146,12 @@ class Module { ? transformCode(this, content) : Promise.resolve({code: content}); - return codePromise.then(({code, dependencies, asyncDependencies}) => { + return codePromise.then(({code, dependencies}) => { const {deps} = this._extractor(code); return { id, code, dependencies: dependencies || deps.sync, - asyncDependencies: asyncDependencies || deps.async, }; }); } diff --git a/react-packager/src/DependencyResolver/__tests__/Module-test.js b/react-packager/src/DependencyResolver/__tests__/Module-test.js index 4ed5868b..71bc5522 100644 --- a/react-packager/src/DependencyResolver/__tests__/Module-test.js +++ b/react-packager/src/DependencyResolver/__tests__/Module-test.js @@ -167,45 +167,6 @@ describe('Module', () => { }); }); - describe('Async Dependencies', () => { - function expectAsyncDependenciesToEqual(expected) { - const module = createModule(); - return module.getAsyncDependencies().then(actual => - expect(actual).toEqual(expected) - ); - } - - pit('should recognize single dependency', () => { - mockIndexFile('System.' + 'import("dep1")'); - - return expectAsyncDependenciesToEqual([['dep1']]); - }); - - pit('should parse single quoted dependencies', () => { - mockIndexFile('System.' + 'import(\'dep1\')'); - - return expectAsyncDependenciesToEqual([['dep1']]); - }); - - pit('should parse multiple async dependencies on the same module', () => { - mockIndexFile([ - 'System.' + 'import("dep1")', - 'System.' + 'import("dep2")', - ].join('\n')); - - return expectAsyncDependenciesToEqual([ - ['dep1'], - ['dep2'], - ]); - }); - - pit('parse fine new lines', () => { - mockIndexFile('System.' + 'import(\n"dep1"\n)'); - - return expectAsyncDependenciesToEqual([['dep1']]); - }); - }); - describe('Code', () => { const fileContents = 'arbitrary(code)'; beforeEach(function() { @@ -247,7 +208,7 @@ describe('Module', () => { const fileContents = 'arbitrary(code);'; const exampleCode = ` require('a'); - System.import('b'); + arbitrary.code('b'); require('c');`; beforeEach(function() { @@ -268,12 +229,8 @@ describe('Module', () => { transformCode.mockReturnValue(Promise.resolve({code: exampleCode})); const module = createModule({transformCode}); - return Promise.all([ - module.getDependencies(), - module.getAsyncDependencies(), - ]).then(([dependencies, asyncDependencies]) => { + return module.getDependencies().then(dependencies => { expect(dependencies).toEqual(['a', 'c']); - expect(asyncDependencies).toEqual([['b']]); }); }); @@ -285,29 +242,8 @@ describe('Module', () => { })); const module = createModule({transformCode}); - return Promise.all([ - module.getDependencies(), - module.getAsyncDependencies(), - ]).then(([dependencies, asyncDependencies]) => { + return module.getDependencies().then(dependencies => { expect(dependencies).toEqual(mockedDependencies); - expect(asyncDependencies).toEqual([['b']]); - }); - }); - - pit('uses async dependencies that `transformCode` resolves to, instead of extracting them', () => { - const mockedAsyncDependencies = [['foo', 'bar'], ['baz']]; - transformCode.mockReturnValue(Promise.resolve({ - code: exampleCode, - asyncDependencies: mockedAsyncDependencies, - })); - const module = createModule({transformCode}); - - return Promise.all([ - module.getDependencies(), - module.getAsyncDependencies(), - ]).then(([dependencies, asyncDependencies]) => { - expect(dependencies).toEqual(['a', 'c']); - expect(asyncDependencies).toEqual(mockedAsyncDependencies); }); }); diff --git a/react-packager/src/DependencyResolver/lib/extractRequires.js b/react-packager/src/DependencyResolver/lib/extractRequires.js index 107cc6ba..5dbf63cc 100644 --- a/react-packager/src/DependencyResolver/lib/extractRequires.js +++ b/react-packager/src/DependencyResolver/lib/extractRequires.js @@ -18,7 +18,6 @@ const lineCommentRe = /\/\/.+(\n|$)/g; function extractRequires(code) { var deps = { sync: [], - async: [], }; code = code @@ -41,15 +40,6 @@ function extractRequires(code) { deps.sync.push(dep); return match; }) - // Parse async dependencies this module has. As opposed to what happens - // with sync dependencies, when the module is required, it's async - // dependencies won't be loaded into memory. This is deferred till the - // code path gets to the import statement: - // System.import('dep1') - .replace(replacePatterns.SYSTEM_IMPORT_RE, (match, pre, quot, dep, post) => { - deps.async.push([dep]); - return match; - }); return {code, deps}; } diff --git a/react-packager/src/DependencyResolver/lib/replacePatterns.js b/react-packager/src/DependencyResolver/lib/replacePatterns.js index a4e563d2..8c10710e 100644 --- a/react-packager/src/DependencyResolver/lib/replacePatterns.js +++ b/react-packager/src/DependencyResolver/lib/replacePatterns.js @@ -12,4 +12,3 @@ exports.IMPORT_RE = /(\bimport\s+(?:[^'"]+\s+from\s+)??)(['"])([^'"]+)(\2)/g; exports.EXPORT_RE = /(\bexport\s+(?:[^'"]+\s+from\s+)??)(['"])([^'"]+)(\2)/g; exports.REQUIRE_RE = /(\brequire\s*?\(\s*?)(['"])([^'"]+)(\2\s*?\))/g; -exports.SYSTEM_IMPORT_RE = /(\bSystem\.import\s*?\(\s*?)(['"])([^'"]+)(\2\s*?\))/g; diff --git a/react-packager/src/Resolver/__tests__/Resolver-test.js b/react-packager/src/Resolver/__tests__/Resolver-test.js index 7ef335d9..2f1f65de 100644 --- a/react-packager/src/Resolver/__tests__/Resolver-test.js +++ b/react-packager/src/Resolver/__tests__/Resolver-test.js @@ -37,10 +37,9 @@ describe('Resolver', function() { }); class ResolutionResponseMock { - constructor({dependencies, mainModuleId, asyncDependencies}) { + constructor({dependencies, mainModuleId}) { this.dependencies = dependencies; this.mainModuleId = mainModuleId; - this.asyncDependencies = asyncDependencies; } prependDependency(dependency) { @@ -80,7 +79,6 @@ describe('Resolver', function() { return Promise.resolve(new ResolutionResponseMock({ dependencies: deps, mainModuleId: 'index', - asyncDependencies: [], })); }); @@ -180,7 +178,6 @@ describe('Resolver', function() { return Promise.resolve(new ResolutionResponseMock({ dependencies: deps, mainModuleId: 'index', - asyncDependencies: [], })); }); @@ -208,7 +205,6 @@ describe('Resolver', function() { return Promise.resolve(new ResolutionResponseMock({ dependencies: deps, mainModuleId: 'index', - asyncDependencies: [], })); }); @@ -637,7 +633,6 @@ describe('Resolver', function() { const resolutionResponse = new ResolutionResponseMock({ dependencies: [module], mainModuleId: 'test module', - asyncDependencies: [], }); resolutionResponse.getResolvedDependencyPairs = (module) => { diff --git a/react-packager/src/Resolver/polyfills/__tests__/loadBundles-test.js b/react-packager/src/Resolver/polyfills/__tests__/loadBundles-test.js deleted file mode 100644 index 39d68788..00000000 --- a/react-packager/src/Resolver/polyfills/__tests__/loadBundles-test.js +++ /dev/null @@ -1,63 +0,0 @@ -/** - * 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. - */ -'use strict'; - -jest.dontMock('../loadBundles'); -jest.mock('NativeModules'); - -let loadBundles; -let loadBundlesCalls; - -describe('loadBundles', () => { - beforeEach(() => { - loadBundles = jest.genMockFunction(); - loadBundlesCalls = loadBundles.mock.calls; - require('NativeModules').RCTBundlesLoader = {loadBundles}; - - require('../loadBundles'); - }); - - it('should set `global.__loadBundles` function when polyfill is initialized', () => { - expect(typeof global.__loadBundles).toBe('function'); - }); - - it('should return a promise', () => { - loadBundles.mockImpl((bundles, callback) => callback()); - expect(global.__loadBundles(['bundle.0']) instanceof Promise).toBeTruthy(); - }); - - pit('shouldn\'t request already loaded bundles', () => { - loadBundles.mockImpl((bundles, callback) => callback()); - return global.__loadBundles(['bundle.0']) - .then(() => global.__loadBundles(['bundle.0'])) - .then(() => expect(loadBundlesCalls.length).toBe(1)); - }); - - pit('shouldn\'n request inflight bundles', () => { - loadBundles.mockImpl((bundles, callback) => { - if (bundles.length === 1 && bundles[0] === 'bundle.0') { - setTimeout(callback, 1000); - } else if (bundles.length === 1 && bundles[0] === 'bundle.1') { - setTimeout(callback, 500); - } - }); - - const promises = Promise.all([ - global.__loadBundles(['bundle.0']), - global.__loadBundles(['bundle.0', 'bundle.1']), - ]).then(() => { - expect(loadBundlesCalls.length).toBe(2); - expect(loadBundlesCalls[0][0][0]).toBe('bundle.0'); - expect(loadBundlesCalls[1][0][0]).toBe('bundle.1'); - }); - - jest.runAllTimers(); - return promises; - }); -}); diff --git a/react-packager/src/Resolver/polyfills/loadBundles.js b/react-packager/src/Resolver/polyfills/loadBundles.js deleted file mode 100644 index 7bb9be10..00000000 --- a/react-packager/src/Resolver/polyfills/loadBundles.js +++ /dev/null @@ -1,34 +0,0 @@ -/* eslint strict:0 */ - -let loadBundlesOnNative = (bundles) => - new Promise((resolve) => - require('NativeModules').RCTBundlesLoader.loadBundles(bundles, resolve)); - -let requestedBundles = Object.create(null); - -/** - * Returns a promise that is fulfilled once all the indicated bundles are - * loaded into memory and injected into the JS engine. - * This invokation might need to go through the bridge - * and run native code to load some, if not all, the requested bundles. - * If all the bundles have already been loaded, the promise is resolved - * immediately. Otherwise, we'll determine which bundles still need to get - * loaded considering both, the ones already loaded, and the ones being - * currently asynchronously loaded by other invocations to `__loadBundles`, - * and return a promise that will get fulfilled once all these are finally - * loaded. - * - * Note this function should only be invoked by generated code. - */ -global.__loadBundles = function(bundles) { - // split bundles by whether they've already been requested or not - const bundlesToRequest = bundles.filter(b => !requestedBundles[b]); - - // keep a reference to the promise loading each bundle - if (bundlesToRequest.length > 0) { - const nativePromise = loadBundlesOnNative(bundlesToRequest); - bundlesToRequest.forEach(b => requestedBundles[b] = nativePromise); - } - - return Promise.all(bundles.map(bundle => requestedBundles[bundle])); -}; diff --git a/react-packager/src/transforms/babel-plugin-system-import/__tests__/babel-plugin-system-import-test.js b/react-packager/src/transforms/babel-plugin-system-import/__tests__/babel-plugin-system-import-test.js deleted file mode 100644 index b29f1bd5..00000000 --- a/react-packager/src/transforms/babel-plugin-system-import/__tests__/babel-plugin-system-import-test.js +++ /dev/null @@ -1,71 +0,0 @@ -/** - * 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('../'), { 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); - }); -}); diff --git a/react-packager/src/transforms/babel-plugin-system-import/index.js b/react-packager/src/transforms/babel-plugin-system-import/index.js deleted file mode 100644 index 7cf0f0a0..00000000 --- a/react-packager/src/transforms/babel-plugin-system-import/index.js +++ /dev/null @@ -1,63 +0,0 @@ -/** - * 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'; - -const t = require('babel-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() { - return { - visitor: { - CallExpression: function (path, state) { - if (!isAppropriateSystemImportCall(path.node)) { - return; - } - - var bundlesLayout = state.opts.bundlesLayout; - var bundleID = bundlesLayout.getBundleIDForModule( - path.node.arguments[0].value - ); - - var bundles = bundleID.split('.'); - bundles.splice(0, 1); - bundles = bundles.map(function(id) { - return t.stringLiteral('bundle.' + id); - }); - - path.replaceWith(t.callExpression( - t.identifier('loadBundles'), - [t.arrayExpression(bundles)] - )); - }, - }, - }; -}; - -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 === 'StringLiteral' - ); -}