Skip to content

Commit

Permalink
Fix builtin loaders with --target=node (#981)
Browse files Browse the repository at this point in the history
  • Loading branch information
fathyb authored and devongovett committed Mar 28, 2018
1 parent e26d443 commit 9d6061c
Show file tree
Hide file tree
Showing 14 changed files with 223 additions and 100 deletions.
3 changes: 3 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,8 @@
"env": {
"node": true,
"es6": true
},
"globals": {
"parcelRequire": true
}
}
16 changes: 7 additions & 9 deletions src/Bundler.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,13 @@ class Bundler extends EventEmitter {
this.delegate = options.delegate || {};
this.bundleLoaders = {};

this.addBundleLoader(
'wasm',
require.resolve('./builtins/loaders/wasm-loader')
);
this.addBundleLoader(
'css',
require.resolve('./builtins/loaders/css-loader')
);
this.addBundleLoader('js', require.resolve('./builtins/loaders/js-loader'));
const loadersPath = `./builtins/loaders/${
options.target === 'node' ? 'node' : 'browser'
}/`;

this.addBundleLoader('wasm', require.resolve(loadersPath + 'wasm-loader'));
this.addBundleLoader('css', require.resolve(loadersPath + 'css-loader'));
this.addBundleLoader('js', require.resolve(loadersPath + 'js-loader'));

this.pending = false;
this.loadedAssets = new Map();
Expand Down
8 changes: 4 additions & 4 deletions src/builtins/hmr-runtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ if ((!parent || !parent.isParcelRequire) && typeof WebSocket !== 'undefined') {

if (data.type === 'update') {
data.assets.forEach(function (asset) {
hmrApply(global.require, asset);
hmrApply(global.parcelRequire, asset);
});

data.assets.forEach(function (asset) {
if (!asset.isNew) {
hmrAccept(global.require, asset.id);
hmrAccept(global.parcelRequire, asset.id);
}
});
}
Expand Down Expand Up @@ -169,7 +169,7 @@ function hmrAccept(bundle, id) {
return true;
}

return getParents(global.require, id).some(function (id) {
return hmrAccept(global.require, id)
return getParents(global.parcelRequire, id).some(function (id) {
return hmrAccept(global.parcelRequire, id)
});
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
4 changes: 4 additions & 0 deletions src/builtins/loaders/node/css-loader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// loading a CSS style is a no-op in Node.js
module.exports = function loadCSSBundle() {
return Promise.resolve();
};
16 changes: 16 additions & 0 deletions src/builtins/loaders/node/js-loader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
var fs = require('fs');

module.exports = function loadJSBundle(bundle) {
return new Promise(function(resolve, reject) {
fs.readFile(__dirname + bundle, 'utf8', function(err, data) {
if (err) {
reject(err);
} else {
resolve(data);
}
});
})
.then(function(code) {
new Function('', code)();
});
};
19 changes: 19 additions & 0 deletions src/builtins/loaders/node/wasm-loader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
var fs = require('fs');

module.exports = function loadWASMBundle(bundle) {
return new Promise(function(resolve, reject) {
fs.readFile(__dirname + bundle, function(err, data) {
if (err) {
reject(err);
} else {
resolve(data.buffer);
}
});
})
.then(function(data) {
return WebAssembly.instantiate(data);
})
.then(function(wasmModule) {
return wasmModule.instance.exports;
});
};
12 changes: 9 additions & 3 deletions src/builtins/prelude.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,18 @@
// orig method which is the require for previous bundles

// eslint-disable-next-line no-global-assign
require = (function (modules, cache, entry) {
parcelRequire = (function (modules, cache, entry) {
// Save the require from previous bundle to this closure if any
var previousRequire = typeof require === "function" && require;
var previousRequire = typeof parcelRequire === 'function' && parcelRequire;
var nodeRequire = typeof require === 'function' && require;

function newRequire(name, jumped) {
if (!cache[name]) {
if (!modules[name]) {
// if we cannot find the module within our internal map or
// cache jump to the current global require ie. the last bundle
// that was added to the page.
var currentRequire = typeof require === "function" && require;
var currentRequire = typeof parcelRequire === 'function' && parcelRequire;
if (!jumped && currentRequire) {
return currentRequire(name, true);
}
Expand All @@ -30,6 +31,11 @@ require = (function (modules, cache, entry) {
return previousRequire(name, true);
}

// Try the node require function if it exists.
if (nodeRequire && typeof name === 'string') {
return nodeRequire(name);
}

var err = new Error('Cannot find module \'' + name + '\'');
err.code = 'MODULE_NOT_FOUND';
throw err;
Expand Down
36 changes: 33 additions & 3 deletions test/javascript.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,38 @@ describe('javascript', function() {
assert.equal(output.default(), 3);
});

it('should split bundles when a dynamic import is used', async function() {
let b = await bundle(__dirname + '/integration/dynamic/index.js');
it('should split bundles when a dynamic import is used with --target=browser', async function() {
let b = await bundle(__dirname + '/integration/dynamic/index.js', {
target: 'browser'
});

assertBundleTree(b, {
name: 'index.js',
assets: ['index.js', 'bundle-loader.js', 'bundle-url.js', 'js-loader.js'],
childBundles: [
{
type: 'map'
},
{
assets: ['local.js'],
childBundles: [
{
type: 'map'
}
]
}
]
});

let output = run(b);
assert.equal(typeof output, 'function');
assert.equal(await output(), 3);
});

it('should split bundles when a dynamic import is used with --target=node', async function() {
let b = await bundle(__dirname + '/integration/dynamic/index.js', {
target: 'node'
});

assertBundleTree(b, {
name: 'index.js',
Expand Down Expand Up @@ -641,7 +671,7 @@ describe('javascript', function() {
// Transpiled destructuring, like r = p.prop1, o = p.prop2, a = p.prop3;
const prodRegExp = /\w ?= ?\w\.prop1, ?\w ?= ?\w\.prop2, ?\w ?= ?\w\.prop3;/;
// ES6 Destructuring, like in the source;
const devRegExp = /const ?{prop1, ?prop2, ?prop3} ?= ?.*/;
const devRegExp = /const ?{\s*prop1,\s*prop2,\s*prop3\s*} ?= ?.*/;
let file;
// Dev build test
await bundle(__dirname + projectBasePath + '/index.js');
Expand Down
35 changes: 34 additions & 1 deletion test/rust.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ describe('rust', function() {
return;
}

it('should generate a wasm file from a rust file with rustc', async function() {
it('should generate a wasm file from a rust file with rustc with --target=browser', async function() {
this.timeout(500000);
let b = await bundle(__dirname + '/integration/rust/index.js');

Expand Down Expand Up @@ -43,6 +43,39 @@ describe('rust', function() {
assert(fs.statSync(Array.from(b.childBundles)[0].name).size > 500);
});

it('should generate a wasm file from a rust file with rustc with --target=node', async function() {
this.timeout(500000);
let b = await bundle(__dirname + '/integration/rust/index.js', {
target: 'node'
});

assertBundleTree(b, {
name: 'index.js',
assets: [
'bundle-loader.js',
'bundle-url.js',
'index.js',
'wasm-loader.js'
],
childBundles: [
{
type: 'wasm',
assets: ['add.rs'],
childBundles: []
},
{
type: 'map'
}
]
});

var res = await run(b);
assert.equal(res, 5);

// not minified
assert(fs.statSync(Array.from(b.childBundles)[0].name).size > 500);
});

it('should support rust files with dependencies via rustc', async function() {
this.timeout(500000);
let b = bundler(__dirname + '/integration/rust-deps/index.js');
Expand Down
12 changes: 8 additions & 4 deletions test/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,26 +106,30 @@ function prepareBrowserContext(bundle, globals) {
);

ctx.window = ctx;

return ctx;
}

function prepareNodeContext(bundle, globals) {
var mod = new Module(bundle.name);
mod.paths = [path.dirname(bundle.name) + '/node_modules'];

return Object.assign(
var ctx = Object.assign(
{
module: mod,
__filename: bundle.name,
__dirname: path.dirname(bundle.name),
require: function(path) {
return mod.require(path);
},
process: process
console,
process: process,
setTimeout: setTimeout
},
globals
);

ctx.global = ctx;
return ctx;
}

function run(bundle, globals, opts = {}) {
Expand All @@ -149,7 +153,7 @@ function run(bundle, globals, opts = {}) {
vm.runInContext(fs.readFileSync(bundle.name), ctx);

if (opts.require !== false) {
return ctx.require(bundle.entryAsset.id);
return ctx.parcelRequire(bundle.entryAsset.id);
}

return ctx;
Expand Down
Loading

0 comments on commit 9d6061c

Please sign in to comment.