Skip to content

Commit

Permalink
Merge branch 'master' of github.com:parcel-bundler/parcel into featur…
Browse files Browse the repository at this point in the history
…e/strip-type-module-attr

* 'master' of github.com:parcel-bundler/parcel:
  Update deps & gitattributes (parcel-bundler#3006)
  Fix assigning to exports from inside a function in scope hoisting (parcel-bundler#2994)
  Define __esModule interop flag when requiring ES module from CommonJS (parcel-bundler#2993)
  Replace module.require in scope hoisting (parcel-bundler#2875)
  Clear scope cache before crawling (parcel-bundler#2986)
  Fix CI (parcel-bundler#2990)
  Shake exports with pure property assignments (parcel-bundler#2979)
  Update postcss.js (parcel-bundler#2922)
  Fail immediately if yarn.lock updates are needed (parcel-bundler#2945)

# Conflicts:
#	packages/core/parcel-bundler/package.json
#	yarn.lock
  • Loading branch information
twome committed May 12, 2019
2 parents 51cf63e + ee0acf2 commit 662e27c
Show file tree
Hide file tree
Showing 26 changed files with 964 additions and 822 deletions.
7 changes: 7 additions & 0 deletions .gitattributes
@@ -0,0 +1,7 @@
# Always use unix style line-endings
* text eol=lf
*.jpeg binary
*.jpg binary
*.png binary
*.wasm binary
*.woff2 binary
1 change: 1 addition & 0 deletions .prettierrc
@@ -1,4 +1,5 @@
{
"singleQuote": true,
"bracketSpacing": false,
"endOfLine": "lf"
}
4 changes: 3 additions & 1 deletion azure-pipelines-template.yml
Expand Up @@ -36,7 +36,9 @@ jobs:
cargo -V
displayName: Install Rust
- script: yarn
# use `--frozen-lockfile` to fail immediately if the committed yarn.lock needs updates
# https://yarnpkg.com/lang/en/docs/cli/install/#toc-yarn-install-frozen-lockfile
- script: yarn --frozen-lockfile
displayName: 'Install dependencies'
- script: yarn test-ci
displayName: 'Run tests'
Expand Down
2 changes: 1 addition & 1 deletion packages/core/babel-register/package.json
Expand Up @@ -13,6 +13,6 @@
"@babel/core": "^7.0.0"
},
"dependencies": {
"@babel/register": "^7.0.0"
"@babel/register": "^7.4.4"
}
}
2 changes: 1 addition & 1 deletion packages/core/integration-tests/package.json
Expand Up @@ -12,7 +12,7 @@
"test-ci": "yarn test --reporter mocha-multi-reporters --reporter-options configFile=./test/mochareporters.json"
},
"devDependencies": {
"@babel/core": "^7.2.0",
"@babel/core": "^7.4.4",
"@jetbrains/kotlinc-js-api": "^1.2.12",
"@parcel/fs": "^1.11.0",
"@parcel/test-utils": "^1.12.0",
Expand Down
@@ -0,0 +1,4 @@
var b = require('./b');

b.setValue(2);
module.exports = b.value;
@@ -0,0 +1,3 @@
exports.setValue = function (value) {
exports.value = value;
}
@@ -0,0 +1 @@
module.exports = require('./b');
@@ -0,0 +1 @@
export default 2;
@@ -1,6 +1,7 @@
output = {
id: module.id,
hot: module.hot,
moduleRequire: module.require,
type: typeof module,
exports: exports,
exportsType: typeof exports,
Expand Down
@@ -0,0 +1,2 @@
import Test from './b';
output = Test.create();
@@ -0,0 +1,9 @@
export default class Test {
constructor() {
this.foo = 'bar';
}

static create() {
return new Test();
}
}
@@ -0,0 +1,5 @@
{
"name": "default-export-class-rename",
"private": true,
"browserslist": ["last 1 Chrome version"]
}
@@ -0,0 +1,3 @@
import {foo} from './b';

output = foo;
@@ -0,0 +1,4 @@
export const foo = 2;

export function bar() {}
bar.displayName = 'hello';
2 changes: 1 addition & 1 deletion packages/core/integration-tests/test/mochareporters.json
@@ -1,5 +1,5 @@
{
"reporterEnabled": "mocha-junit-reporter",
"reporterEnabled": "spec, mocha-junit-reporter",
"mochaJunitReporterReporterOptions": {
"mochaFile": "junit-testresults.xml"
}
Expand Down
57 changes: 57 additions & 0 deletions packages/core/integration-tests/test/scope-hoisting.js
Expand Up @@ -549,6 +549,37 @@ describe('scope hoisting', function() {
let output = await run(b);
assert.deepEqual(output, 'bar');
});

it('should shake pure property assignments', async function() {
let b = await bundle(
path.join(
__dirname,
'/integration/scope-hoisting/es6/pure-assignment/a.js'
)
);

let output = await run(b);
assert.deepEqual(output, 2);

let contents = await fs.readFile(
path.join(__dirname, 'dist/a.js'),
'utf8'
);
assert(!/bar/.test(contents));
assert(!/displayName/.test(contents));
});

it('should correctly rename references to default exported classes', async function() {
let b = await bundle(
path.join(
__dirname,
'/integration/scope-hoisting/es6/default-export-class-rename/a.js'
)
);

let output = await run(b);
assert.deepEqual(output.foo, 'bar');
});
});

describe('commonjs', function() {
Expand Down Expand Up @@ -877,6 +908,7 @@ describe('scope hoisting', function() {
let output = await run(b);
assert.equal(output.id, b.entryAsset.id);
assert.equal(output.hot, null);
assert.equal(output.moduleRequire, null);
assert.equal(output.type, 'object');
assert.deepEqual(output.exports, {});
assert.equal(output.exportsType, 'object');
Expand Down Expand Up @@ -1172,5 +1204,30 @@ describe('scope hoisting', function() {
let output = await run(b);
assert.deepEqual(output, 42);
});

it('should insert __esModule interop flag when importing from an ES module', async function() {
let b = await bundle(
path.join(
__dirname,
'/integration/scope-hoisting/commonjs/interop-require-es-module/a.js'
)
);

let output = await run(b);
assert.equal(output.__esModule, true);
assert.equal(output.default, 2);
});

it('should support assigning to exports from inside a function', async function() {
let b = await bundle(
path.join(
__dirname,
'/integration/scope-hoisting/commonjs/export-assign-scope/a.js'
)
);

let output = await run(b);
assert.deepEqual(output, 2);
});
});
});
37 changes: 19 additions & 18 deletions packages/core/parcel-bundler/package.json
Expand Up @@ -15,18 +15,18 @@
"index.js"
],
"dependencies": {
"@babel/code-frame": "^7.0.0 <7.4.0",
"@babel/core": "^7.4.0",
"@babel/generator": "^7.4.0",
"@babel/parser": "^7.4.2",
"@babel/plugin-transform-flow-strip-types": "^7.4.0",
"@babel/plugin-transform-modules-commonjs": "^7.4.0",
"@babel/plugin-transform-react-jsx": "^7.0.0 <7.4.0",
"@babel/preset-env": "^7.4.2",
"@babel/runtime": "^7.4.2",
"@babel/template": "^7.4.0",
"@babel/traverse": "^7.4.0",
"@babel/types": "^7.4.0",
"@babel/code-frame": "^7.0.0",
"@babel/core": "^7.4.4",
"@babel/generator": "^7.4.4",
"@babel/parser": "^7.4.4",
"@babel/plugin-transform-flow-strip-types": "^7.4.4",
"@babel/plugin-transform-modules-commonjs": "^7.4.4",
"@babel/plugin-transform-react-jsx": "^7.0.0",
"@babel/preset-env": "^7.4.4",
"@babel/runtime": "^7.4.4",
"@babel/template": "^7.4.4",
"@babel/traverse": "^7.4.4",
"@babel/types": "^7.4.4",
"@iarna/toml": "^2.2.0",
"@parcel/fs": "^1.11.0",
"@parcel/logger": "^1.11.0",
Expand All @@ -40,6 +40,7 @@
"clone": "^2.1.1",
"command-exists": "^1.2.6",
"commander": "^2.11.0",
"core-js": "^2.6.5",
"cross-spawn": "^6.0.4",
"css-modules-loader-core": "^1.1.0",
"cssnano": "^4.0.0",
Expand Down Expand Up @@ -74,10 +75,10 @@
"ws": "^5.1.1"
},
"devDependencies": {
"@babel/cli": "^7.0.0 <7.4.0",
"@babel/plugin-syntax-export-default-from": "^7.0.0 <7.4.0",
"@babel/plugin-syntax-export-namespace-from": "^7.0.0 <7.4.0",
"@babel/plugin-transform-runtime": "^7.4.0",
"@babel/cli": "^7.4.4",
"@babel/plugin-syntax-export-default-from": "^7.0.0",
"@babel/plugin-syntax-export-namespace-from": "^7.0.0",
"@babel/plugin-transform-runtime": "^7.4.4",
"@babel/preset-flow": "^7.0.0 <7.4.0",
"@parcel/babel-register": "^1.11.0 <7.4.0",
"@parcel/test-utils": "^1.12.0",
Expand All @@ -89,7 +90,7 @@
"codecov": "^3.0.0",
"coffeescript": "^2.0.3",
"cross-env": "^5.1.1",
"elm": "^0.19.0",
"elm": "^0.19.0-bugfix6",
"elm-hot": "^1.0.1",
"eslint": "^4.13.0",
"glslify-bundle": "^5.0.0",
Expand All @@ -104,7 +105,7 @@
"mocha-multi-reporters": "^1.1.7",
"ncp": "^2.0.0",
"nib": "^1.1.2",
"node-elm-compiler": "^5.0.1",
"node-elm-compiler": "^5.0.3",
"nyc": "^11.1.0",
"postcss-modules": "^1.4.1",
"posthtml-extend": "^0.2.1",
Expand Down
3 changes: 2 additions & 1 deletion packages/core/parcel-bundler/src/Asset.js
Expand Up @@ -9,6 +9,7 @@ const syncPromise = require('./utils/syncPromise');
const logger = require('@parcel/logger');
const Resolver = require('./Resolver');
const objectHash = require('./utils/objectHash');
const t = require('babel-types');

/**
* An Asset represents a file in the dependency tree. Assets can have multiple
Expand Down Expand Up @@ -204,7 +205,7 @@ class Asset {
if (!this.id) {
this.id =
this.options.production || this.options.scopeHoist
? md5(this.relativeName, 'base64').slice(0, 4)
? t.toIdentifier(md5(this.relativeName, 'base64')).slice(0, 4)
: this.relativeName;
}

Expand Down
4 changes: 4 additions & 0 deletions packages/core/parcel-bundler/src/builtins/helpers.js
Expand Up @@ -4,6 +4,10 @@ function $parcel$interopDefault(a) {
: {d: a};
}

function $parcel$defineInteropFlag(a) {
Object.defineProperty(a, '__esModule', {value: true});
}

function $parcel$exportWildcard(dest, source) {
Object.keys(source).forEach(function(key) {
if(key === "default" || key === "__esModule") {
Expand Down
27 changes: 26 additions & 1 deletion packages/core/parcel-bundler/src/scope-hoisting/concat.js
Expand Up @@ -9,6 +9,7 @@ const {getName, getIdentifier} = require('./utils');

const EXPORTS_RE = /^\$([^$]+)\$exports$/;

const ESMODULE_TEMPLATE = template(`$parcel$defineInteropFlag(EXPORTS);`);
const DEFAULT_INTEROP_TEMPLATE = template(
'var NAME = $parcel$interopDefault(MODULE)'
);
Expand Down Expand Up @@ -142,10 +143,11 @@ module.exports = (packager, ast) => {
);
}

let asset = assets.get(id.value);
let mod = packager.resolveModule(id.value, source.value);

if (!mod) {
if (assets.get(id.value).dependencies.get(source.value).optional) {
if (asset.dependencies.get(source.value).optional) {
path.replaceWith(
THROW_TEMPLATE({MODULE: t.stringLiteral(source.value)})
);
Expand All @@ -161,6 +163,29 @@ module.exports = (packager, ast) => {
if (!isUnusedValue(path)) {
let name = getName(mod, 'exports');
node = t.identifier(replacements.get(name) || name);

// Insert __esModule interop flag if the required module is an ES6 module with a default export.
// This ensures that code generated by Babel and other tools works properly.
if (
asset.cacheData.isCommonJS &&
mod.cacheData.isES6Module &&
mod.cacheData.exports.default
) {
let binding = path.scope.getBinding(name);
if (binding && !binding.path.getData('hasESModuleFlag')) {
if (binding.path.node.init) {
binding.path
.getStatementParent()
.insertAfter(ESMODULE_TEMPLATE({EXPORTS: name}));
}

for (let path of binding.constantViolations) {
path.insertAfter(ESMODULE_TEMPLATE({EXPORTS: name}));
}

binding.path.setData('hasESModuleFlag', true);
}
}
}

// We need to wrap the module in a function when a require
Expand Down
31 changes: 25 additions & 6 deletions packages/core/parcel-bundler/src/scope-hoisting/hoist.js
Expand Up @@ -2,6 +2,7 @@ const path = require('path');
const mm = require('micromatch');
const t = require('@babel/types');
const template = require('@babel/template').default;
const traverse = require('@babel/traverse').default;
const rename = require('./renamer');
const {getName, getIdentifier, getExportIdentifier} = require('./utils');

Expand Down Expand Up @@ -51,6 +52,7 @@ function hasSideEffects(asset, {sideEffects} = asset._package) {
module.exports = {
Program: {
enter(path, asset) {
traverse.cache.clearScope();
path.scope.crawl();

asset.cacheData.imports = asset.cacheData.imports || Object.create(null);
Expand Down Expand Up @@ -189,6 +191,13 @@ module.exports = {
path.replaceWith(t.identifier('null'));
}

if (
t.matchesPattern(path.node, 'module.require') &&
asset.options.target !== 'node'
) {
path.replaceWith(t.identifier('null'));
}

if (t.matchesPattern(path.node, 'module.bundle')) {
path.replaceWith(t.identifier('require'));
}
Expand Down Expand Up @@ -259,13 +268,23 @@ module.exports = {
let scope = path.scope.getProgramParent();
if (!scope.hasBinding(identifier.name)) {
asset.cacheData.exports[name] = identifier.name;
let [decl] = path.insertBefore(
t.variableDeclaration('var', [
t.variableDeclarator(t.clone(identifier), right)
])
);

scope.registerDeclaration(decl);
// If in the program scope, create a variable declaration and initialize with the exported value.
// Otherwise, declare the variable in the program scope, and assign to it here.
if (path.scope === scope) {
let [decl] = path.insertBefore(
t.variableDeclaration('var', [
t.variableDeclarator(t.clone(identifier), right)
])
);

scope.registerDeclaration(decl);
} else {
scope.push({id: t.clone(identifier)});
path.insertBefore(
t.assignmentExpression('=', t.clone(identifier), right)
);
}
} else {
path.insertBefore(
t.assignmentExpression('=', t.clone(identifier), right)
Expand Down

0 comments on commit 662e27c

Please sign in to comment.