diff --git a/.eslintrc.json b/.eslintrc.json index 99af1fe5342..d3c9e011a87 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -13,5 +13,8 @@ "globals": { "parcelRequire": true, "define": true + }, + "rules": { + "no-return-await": "error" } } diff --git a/packages/core/integration-tests/test/hmr.js b/packages/core/integration-tests/test/hmr.js index 9579ef502cb..0fe734ce817 100644 --- a/packages/core/integration-tests/test/hmr.js +++ b/packages/core/integration-tests/test/hmr.js @@ -392,6 +392,45 @@ describe('hmr', function() { assert.deepEqual(outputs, [3, 10]); }); + it('should bubble up HMR events to a page reload', async function() { + await ncp( + path.join(__dirname, '/integration/hmr-reload'), + path.join(__dirname, '/input') + ); + + b = bundler(path.join(__dirname, '/input/index.js'), { + watch: true, + hmr: true + }); + let bundle = await b.bundle(); + + let outputs = []; + let ctx = await run( + bundle, + { + output(o) { + outputs.push(o); + } + }, + {require: false} + ); + let spy = sinon.spy(ctx.location, 'reload'); + + await sleep(50); + assert.deepEqual(outputs, [3]); + assert(spy.notCalled); + + await sleep(100); + fs.writeFile( + path.join(__dirname, '/input/local.js'), + 'exports.a = 5; exports.b = 5;' + ); + + await nextEvent(b, 'bundled'); + assert.deepEqual(outputs, [3]); + assert(spy.calledOnce); + }); + it('should log emitted errors and show an error overlay', async function() { await ncp( path.join(__dirname, '/integration/commonjs'), diff --git a/packages/core/integration-tests/test/integration/hmr-circular/index.js b/packages/core/integration-tests/test/integration/hmr-circular/index.js index 72533c84aa2..d46510716d1 100644 --- a/packages/core/integration-tests/test/integration/hmr-circular/index.js +++ b/packages/core/integration-tests/test/integration/hmr-circular/index.js @@ -4,6 +4,8 @@ function run() { output(local.a + local.b); } +module.hot.accept(); + run(); module.exports = 'value'; diff --git a/packages/core/integration-tests/test/integration/hmr-dynamic/index.js b/packages/core/integration-tests/test/integration/hmr-dynamic/index.js index 37ed6fb597c..ee3c1d451fb 100644 --- a/packages/core/integration-tests/test/integration/hmr-dynamic/index.js +++ b/packages/core/integration-tests/test/integration/hmr-dynamic/index.js @@ -6,4 +6,6 @@ function run() { }); }; +module.hot.accept(); + run(); diff --git a/packages/core/integration-tests/test/integration/hmr-reload/index.js b/packages/core/integration-tests/test/integration/hmr-reload/index.js new file mode 100644 index 00000000000..bd54fc09f6e --- /dev/null +++ b/packages/core/integration-tests/test/integration/hmr-reload/index.js @@ -0,0 +1,7 @@ +var local = require('./local'); + +function run() { + output(local.a + local.b); +} + +run(); diff --git a/packages/core/integration-tests/test/integration/hmr-reload/local.js b/packages/core/integration-tests/test/integration/hmr-reload/local.js new file mode 100644 index 00000000000..59aa6ffd125 --- /dev/null +++ b/packages/core/integration-tests/test/integration/hmr-reload/local.js @@ -0,0 +1,2 @@ +exports.a = 1; +exports.b = 2; diff --git a/packages/core/integration-tests/test/integration/hmr/index.js b/packages/core/integration-tests/test/integration/hmr/index.js index bd54fc09f6e..21178bc0101 100644 --- a/packages/core/integration-tests/test/integration/hmr/index.js +++ b/packages/core/integration-tests/test/integration/hmr/index.js @@ -4,4 +4,6 @@ function run() { output(local.a + local.b); } +module.hot.accept(); + run(); diff --git a/packages/core/integration-tests/test/integration/scope-hoisting/es6/dynamic-import-dynamic/a.js b/packages/core/integration-tests/test/integration/scope-hoisting/es6/dynamic-import-dynamic/a.js new file mode 100644 index 00000000000..0888e345bef --- /dev/null +++ b/packages/core/integration-tests/test/integration/scope-hoisting/es6/dynamic-import-dynamic/a.js @@ -0,0 +1 @@ +export default import("./b.js").then(b => b.default); diff --git a/packages/core/integration-tests/test/integration/scope-hoisting/es6/dynamic-import-dynamic/b.js b/packages/core/integration-tests/test/integration/scope-hoisting/es6/dynamic-import-dynamic/b.js new file mode 100644 index 00000000000..30628ea0fbe --- /dev/null +++ b/packages/core/integration-tests/test/integration/scope-hoisting/es6/dynamic-import-dynamic/b.js @@ -0,0 +1 @@ +export default import('./c.js').then(b => b.default + 1); diff --git a/packages/core/integration-tests/test/integration/scope-hoisting/es6/dynamic-import-dynamic/c.js b/packages/core/integration-tests/test/integration/scope-hoisting/es6/dynamic-import-dynamic/c.js new file mode 100644 index 00000000000..67d639a53f2 --- /dev/null +++ b/packages/core/integration-tests/test/integration/scope-hoisting/es6/dynamic-import-dynamic/c.js @@ -0,0 +1 @@ +export default 122; diff --git a/packages/core/integration-tests/test/scope-hoisting.js b/packages/core/integration-tests/test/scope-hoisting.js index d40a48f2ea2..00c4cf24f2c 100644 --- a/packages/core/integration-tests/test/scope-hoisting.js +++ b/packages/core/integration-tests/test/scope-hoisting.js @@ -264,6 +264,18 @@ describe('scope hoisting', function() { assert.equal(await output.default, 5); }); + it('supports nested dynamic imports', async function() { + let b = await bundle( + path.join( + __dirname, + '/integration/scope-hoisting/es6/dynamic-import-dynamic/a.js' + ) + ); + + let output = await run(b); + assert.equal(await output.default, 123); + }); + it('should not export function arguments', async function() { let b = await bundle( path.join( diff --git a/packages/core/parcel-bundler/src/Asset.js b/packages/core/parcel-bundler/src/Asset.js index ce46f9f07e5..381d6e9f817 100644 --- a/packages/core/parcel-bundler/src/Asset.js +++ b/packages/core/parcel-bundler/src/Asset.js @@ -160,7 +160,7 @@ class Asset { return conf; } - return await config.load(opts.path || this.name, filenames); + return config.load(opts.path || this.name, filenames); } return null; @@ -171,7 +171,7 @@ class Asset { } async load() { - return await fs.readFile(this.name, this.encoding); + return fs.readFile(this.name, this.encoding); } parse() { diff --git a/packages/core/parcel-bundler/src/Bundler.js b/packages/core/parcel-bundler/src/Bundler.js index ef52f2339d9..2806990608c 100644 --- a/packages/core/parcel-bundler/src/Bundler.js +++ b/packages/core/parcel-bundler/src/Bundler.js @@ -490,7 +490,7 @@ class Bundler extends EventEmitter { this.options.autoinstall && install ) { - return await this.installDep(asset, dep); + return this.installDep(asset, dep); } err.message = `Cannot resolve dependency '${dep.name}'`; @@ -521,7 +521,7 @@ class Bundler extends EventEmitter { } } - return await this.resolveDep(asset, dep, false); + return this.resolveDep(asset, dep, false); } async throwDepError(asset, dep, err) { diff --git a/packages/core/parcel-bundler/src/Resolver.js b/packages/core/parcel-bundler/src/Resolver.js index c047d1ba211..825e45d45ef 100755 --- a/packages/core/parcel-bundler/src/Resolver.js +++ b/packages/core/parcel-bundler/src/Resolver.js @@ -159,7 +159,7 @@ class Resolver { // First try as a file, then as a directory. return ( (await this.loadAsFile(filename, extensions, pkg)) || - (await this.loadDirectory(filename, extensions, pkg)) + (await this.loadDirectory(filename, extensions, pkg)) // eslint-disable-line no-return-await ); } @@ -251,7 +251,7 @@ class Resolver { } // Fall back to an index file inside the directory. - return await this.loadAsFile(path.join(dir, 'index'), extensions, pkg); + return this.loadAsFile(path.join(dir, 'index'), extensions, pkg); } async readPackage(dir) { diff --git a/packages/core/parcel-bundler/src/SourceMap.js b/packages/core/parcel-bundler/src/SourceMap.js index 3ee3b7ab3e2..222dc3c3365 100644 --- a/packages/core/parcel-bundler/src/SourceMap.js +++ b/packages/core/parcel-bundler/src/SourceMap.js @@ -35,7 +35,7 @@ class SourceMap { } map = typeof map === 'string' ? JSON.parse(map) : map; if (map.sourceRoot) delete map.sourceRoot; - return await new SourceMapConsumer(map); + return new SourceMapConsumer(map); } async addMap(map, lineOffset = 0, columnOffset = 0) { diff --git a/packages/core/parcel-bundler/src/assets/GLSLAsset.js b/packages/core/parcel-bundler/src/assets/GLSLAsset.js index fc69a96cf88..55bf7111d52 100644 --- a/packages/core/parcel-bundler/src/assets/GLSLAsset.js +++ b/packages/core/parcel-bundler/src/assets/GLSLAsset.js @@ -37,7 +37,7 @@ class GLSLAsset extends Asset { } }); - return await promisify(depper.inline.bind(depper))(this.contents, cwd); + return promisify(depper.inline.bind(depper))(this.contents, cwd); } collectDependencies() { diff --git a/packages/core/parcel-bundler/src/assets/LESSAsset.js b/packages/core/parcel-bundler/src/assets/LESSAsset.js index 8a914077e03..8791c289636 100644 --- a/packages/core/parcel-bundler/src/assets/LESSAsset.js +++ b/packages/core/parcel-bundler/src/assets/LESSAsset.js @@ -26,7 +26,7 @@ class LESSAsset extends Asset { opts.sourceMap = {outputSourceFiles: true}; } - return await render(code, opts); + return render(code, opts); } collectDependencies() { diff --git a/packages/core/parcel-bundler/src/assets/RawAsset.js b/packages/core/parcel-bundler/src/assets/RawAsset.js index d44abf2e306..2111341c652 100644 --- a/packages/core/parcel-bundler/src/assets/RawAsset.js +++ b/packages/core/parcel-bundler/src/assets/RawAsset.js @@ -27,7 +27,7 @@ class RawAsset extends Asset { } async generateHash() { - return await md5.file(this.name); + return md5.file(this.name); } } diff --git a/packages/core/parcel-bundler/src/assets/SASSAsset.js b/packages/core/parcel-bundler/src/assets/SASSAsset.js index 936a4c78847..ee27366aac4 100644 --- a/packages/core/parcel-bundler/src/assets/SASSAsset.js +++ b/packages/core/parcel-bundler/src/assets/SASSAsset.js @@ -102,7 +102,7 @@ async function getSassRuntime(searchPath) { return await localRequire('node-sass', searchPath, true); } catch (e) { // If node-sass is not used locally, install dart-sass, as this causes no freezing issues - return await localRequire('sass', searchPath); + return localRequire('sass', searchPath); } } diff --git a/packages/core/parcel-bundler/src/builtins/hmr-runtime.js b/packages/core/parcel-bundler/src/builtins/hmr-runtime.js index 766bb1592ee..989ab860f3c 100644 --- a/packages/core/parcel-bundler/src/builtins/hmr-runtime.js +++ b/packages/core/parcel-bundler/src/builtins/hmr-runtime.js @@ -20,7 +20,7 @@ function Module(moduleName) { } module.bundle.Module = Module; -var updatedAssets; +var checkedAssets, assetsToAccept; var parent = module.bundle.parent; if ((!parent || !parent.isParcelRequire) && typeof WebSocket !== 'undefined') { @@ -28,22 +28,35 @@ if ((!parent || !parent.isParcelRequire) && typeof WebSocket !== 'undefined') { var protocol = location.protocol === 'https:' ? 'wss' : 'ws'; var ws = new WebSocket(protocol + '://' + hostname + ':' + process.env.HMR_PORT + '/'); ws.onmessage = function(event) { - updatedAssets = {}; - + checkedAssets = {}; + assetsToAccept = []; + var data = JSON.parse(event.data); if (data.type === 'update') { - console.clear(); - - data.assets.forEach(function (asset) { - hmrApply(global.parcelRequire, asset); - }); - - data.assets.forEach(function (asset) { + var handled = false; + data.assets.forEach(function(asset) { if (!asset.isNew) { - hmrAccept(global.parcelRequire, asset.id); + var didAccept = hmrAcceptCheck(global.parcelRequire, asset.id); + if (didAccept) { + handled = true; + } } }); + + if(handled){ + console.clear(); + + data.assets.forEach(function (asset) { + hmrApply(global.parcelRequire, asset); + }); + + assetsToAccept.forEach(function (v) { + hmrAcceptRun(v[0], v[1]); + }); + } else { + window.location.reload(); + } } if (data.type === 'reload') { @@ -140,21 +153,35 @@ function hmrApply(bundle, asset) { } } -function hmrAccept(bundle, id) { +function hmrAcceptCheck(bundle, id) { var modules = bundle.modules; if (!modules) { return; } if (!modules[id] && bundle.parent) { - return hmrAccept(bundle.parent, id); + return hmrAcceptCheck(bundle.parent, id); } - if (updatedAssets[id]) { + if (checkedAssets[id]) { return; } - updatedAssets[id] = true; + checkedAssets[id] = true; + + var cached = bundle.cache[id]; + + assetsToAccept.push([bundle, id]) + + if (cached && cached.hot && cached.hot._acceptCallbacks.length) { + return true; + } + return getParents(global.parcelRequire, id).some(function (id) { + return hmrAcceptCheck(global.parcelRequire, id) + }); +} + +function hmrAcceptRun(bundle, id) { var cached = bundle.cache[id]; bundle.hotData = {}; if (cached) { @@ -177,8 +204,4 @@ function hmrAccept(bundle, id) { }); return true; } - - return getParents(global.parcelRequire, id).some(function (id) { - return hmrAccept(global.parcelRequire, id) - }); } diff --git a/packages/core/parcel-bundler/src/packagers/JSConcatPackager.js b/packages/core/parcel-bundler/src/packagers/JSConcatPackager.js index bffd16ed9e8..2c26b52d22a 100644 --- a/packages/core/parcel-bundler/src/packagers/JSConcatPackager.js +++ b/packages/core/parcel-bundler/src/packagers/JSConcatPackager.js @@ -384,6 +384,7 @@ class JSConcatPackager extends Packager { if (this.bundle.assets.has(asset)) { return; } + this.assets.set(asset.id, asset); this.bundle.addAsset(asset); if (!asset.parentBundle) { asset.parentBundle = this.bundle; diff --git a/packages/core/parcel-bundler/src/transforms/babel/babelrc.js b/packages/core/parcel-bundler/src/transforms/babel/babelrc.js index f5a67aac31c..7dc101bffdf 100644 --- a/packages/core/parcel-bundler/src/transforms/babel/babelrc.js +++ b/packages/core/parcel-bundler/src/transforms/babel/babelrc.js @@ -53,12 +53,12 @@ async function getBabelRc(asset, isSource) { } // Otherwise, return the .babelrc if babelify was found - return babelify ? await findBabelRc(asset) : null; + return babelify ? findBabelRc(asset) : null; } // If this asset is not in node_modules, always use the .babelrc if (isSource) { - return await findBabelRc(asset); + return findBabelRc(asset); } // Otherwise, don't load .babelrc for node_modules. @@ -266,7 +266,7 @@ async function installPlugins(asset, babelrc) { let plugins = (babelrc.plugins || []).map(p => resolveModule('plugin', getPluginName(p), asset.name) ); - return await Promise.all([...presets, ...plugins]); + return Promise.all([...presets, ...plugins]); } async function resolveModule(type, name, path) { diff --git a/packages/core/parcel-bundler/src/utils/loadPlugins.js b/packages/core/parcel-bundler/src/utils/loadPlugins.js index 1a9a7c11924..1f3775fc01e 100644 --- a/packages/core/parcel-bundler/src/utils/loadPlugins.js +++ b/packages/core/parcel-bundler/src/utils/loadPlugins.js @@ -2,14 +2,12 @@ const localRequire = require('./localRequire'); module.exports = async function loadPlugins(plugins, relative) { if (Array.isArray(plugins)) { - return await Promise.all( - plugins.map(async p => await loadPlugin(p, relative)).filter(Boolean) + return Promise.all( + plugins.map(p => loadPlugin(p, relative)).filter(Boolean) ); } else if (typeof plugins === 'object') { let mapPlugins = await Promise.all( - Object.keys(plugins).map( - async p => await loadPlugin(p, relative, plugins[p]) - ) + Object.keys(plugins).map(p => loadPlugin(p, relative, plugins[p])) ); return mapPlugins.filter(Boolean); } else { diff --git a/packages/core/parcel-bundler/src/utils/localRequire.js b/packages/core/parcel-bundler/src/utils/localRequire.js index 42a2fd6c950..68ab1e302a8 100644 --- a/packages/core/parcel-bundler/src/utils/localRequire.js +++ b/packages/core/parcel-bundler/src/utils/localRequire.js @@ -22,7 +22,7 @@ async function localResolve(name, path, triedInstall = false) { if (e.code === 'MODULE_NOT_FOUND' && !triedInstall) { const packageName = getModuleParts(name)[0]; await installPackage(packageName, path); - return await localResolve(name, path, true); + return localResolve(name, path, true); } throw e; } diff --git a/packages/core/test-utils/src/utils.js b/packages/core/test-utils/src/utils.js index 57d972ea1f8..63dc8436f53 100644 --- a/packages/core/test-utils/src/utils.js +++ b/packages/core/test-utils/src/utils.js @@ -234,7 +234,7 @@ function prepareBrowserContext(bundle, globals) { document: fakeDocument, WebSocket, console, - location: {hostname: 'localhost'}, + location: {hostname: 'localhost', reload() {}}, fetch(url) { return Promise.resolve({ arrayBuffer() {