Comments (19)
I bring this up because, whew boy are we in enough of the weeds due to incompatibilities of existing CJS interop w/ babel and ESM
from babel-plugin-dynamic-import-webpack.
@bmeck How does something like this sound?
function _specInteropRequireWildcard(obj) {
if (obj && obj.__esModule) {
return obj;
} else {
var newObj = Object.create
? Object.create(null, {
default: {
value: obj,
writable: true,
enumerable: true
},
__esModule: {
value: true
}
})
: {
default: obj,
__esModule: true
};
if (typeof Symbol !== "undefined" && Symbol.toStringTag) {
Object.defineProperty(newObj, Symbol.toStringTag, { value: "Module" });
}
return (Object.freeze || Object)(newObj);
}
}
I've been discussing with @loganfsmyth on slack about implementing a possible spec: true
version of the transform that could use that improved helper, as well as more spec compliant exports (live binding, immutable module record).
from babel-plugin-dynamic-import-webpack.
@Kovensky I've had talks w/ typescript in the past about this, they are aware. This behavior also affects import
declarations.
from babel-plugin-dynamic-import-webpack.
Example requested by https://twitter.com/dan_abramov/status/806506649544491008
This plugin maps import()
to require.ensure()
import
returns the ModuleNamespaceObject of an ESM.
require.ensure
returns the value of module.exports
directly.
CJS interop with ESM cannot create a ModuleNamespaceObject that can proxy to all possible shapes of module.exports
.
Due to this all proposals for interop starting with the original EP have used wrapping mechanics to produce ModuleNamespaceObjects. The exact behavior of wrapping mechanics is still in discussion from talks with VM implementors and TC39 started in September. However, all proposals require the wrapping mechanics to provide a default
and vary on the behavior of named exports.
A good example of breakage should people expect exact mapping to require.ensure
:
(await import('fs')).readFile; // may not work depending on wrapping mechanics
However, if we use the default
that exists in all proposals:
(await import('fs')).default.readFile; // will work in all proposals
To note: this is a babel plugin and should detect non-CJS using __esModule
on CJS to determine if it is acting as an ESM. If it is acting as an ESM it should be sane to not wrap.
from babel-plugin-dynamic-import-webpack.
ah, conversely in the current code:
(await import('fs')).default.readFile;
Does not work, since it doesn't shadow nor wrap default
from babel-plugin-dynamic-import-webpack.
Sounds like migrating to that is going to be particularly painful for TypeScript... it maps commonjs module.exports directly to the namespace, and requires that you do fun things such as call a namespace import as a function if the commonjs exports was a function, etc...
I think that solution will be a good thing (you can't statically verify the imported symbols otherwise), but sounds like it'll take time 😅
from babel-plugin-dynamic-import-webpack.
I had actually expected implementers of a dynamic import plugin for webpack to actually map to System.import, which on webpack's implementation should already have the wrap-in-default behavior for non-ESM (...I think). I presume this went with require.ensure for webpack 1 compatibility...
from babel-plugin-dynamic-import-webpack.
Yes the import() we have implemented is more similar to System.import
from babel-plugin-dynamic-import-webpack.
@Kovensky just in case you were unaware, TypeScript has a flag to model the synthesis of a default export from a CommonJS module. --allowSyntheticDefaultImports
from babel-plugin-dynamic-import-webpack.
@bmeck at the moment I'm operating under the assumption/belief/hope that it will indeed allow named property access. Once the interop story gets more concrete, we can ship a breaking change to this transform that implements the proper semantics.
from babel-plugin-dynamic-import-webpack.
@ljharb can we at least properly set the default
?
from babel-plugin-dynamic-import-webpack.
With the way it's implemented right now, won't Babel do the correctish thing wrt default and named exports?
from babel-plugin-dynamic-import-webpack.
@ljharb no, you need something like:
(new Promise((resolve) => {
require.ensure([], (require) => {
var ns = require(SOURCE);
if (ns && ns.__esModule) {
resolve(ns);
} else {
var wrapper = Object.create(ns);
wrapper.__esModule = true;
wrapper.default = ns;
Object.freeze(wrapper);
resolve(wrapper);
}
});
}))
to get close-ish
from babel-plugin-dynamic-import-webpack.
Right, but if the module.exports
being import()
ed lacks __esModule
, then Babel turns named imports into property access - and if has it, then Babel will pull .default
- no?
from babel-plugin-dynamic-import-webpack.
@ljharb existing shim in babel below:
function _interopRequireWildcard(obj) {
if (obj && obj.__esModule) { return obj; }
else {
var newObj = {};
if (obj != null) {
for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key];
}
}
newObj.default = obj; return newObj;
}
}
.default
is shadowed, but re-export problem from not setting__esModule
- prototype is incorrect
- named imports don't reflect inherited properties (this is one thing under discussion)
- getter don't fully function, mocking/apm/promisifyAll breakage (this is one thing under discussion)
- namespace is mutable
from babel-plugin-dynamic-import-webpack.
@Kovensky sounds good. eventually would be interested in test262 being brought into all this to see % compliance for babel:
TEST_FILES="$(find test262/test -name \*.js)"
mkdir compiled-test262
for FILE in $TEST_FILES; do
babel -o compiled-$FILE < $FILE
done
// with .babelrc for transform-es2015-modules-commonjs
for FILE in $TEST_FILES; do
node --require add-assert-global.js compiled-$FILE
done
but not really going to push that right now since it just checks the runtime behavior of ModuleNamespace, not the actual interop properties.
from babel-plugin-dynamic-import-webpack.
@aluanhaddad does enabling --allowSyntheticDefaultImports
also emit appropriate wrapping code, or does it need to be used in combination with both --modules=es6
and babel/bundler postprocessing?
from babel-plugin-dynamic-import-webpack.
@Kovensky
// test.ts
import {version} from 'express';
import express from 'express';
import * as expressNS from 'express';
import expressAssign = require('express');
console.log(version);
express();
console.log(expressNS.version);
console.log(expressAssign.version);
export default function defaultExport() {}
export let letExport = 0;
// out.js
"use strict";
var express_1 = require("express");
var express_2 = require("express");
var expressNS = require("express");
var expressAssign = require("express");
console.log(express_1.version);
express_2["default"]();
console.log(expressNS.version);
console.log(expressAssign.version);
function defaultExport() { }
exports.__esModule = true;
exports["default"] = defaultExport;
exports.letExport = 0;
{
"compilerOptions": {
"module": "commonjs",
"allowSyntheticDefaultImports": false,
"moduleResolution": "node"
}
}
I actually don't see any impact of swapping allowSyntheticDefaultImports
for my example file.
from babel-plugin-dynamic-import-webpack.
The allowSyntheticDefaultImports
only operates as a type system level. It is not intended to have any effect on code generation but rather to model the behavior of module loaders that provide the default export synthesis. This allows type checking to work correctly while allowing users to enjoy the interop benefits provided by certain loaders. The specific usecase was SystemJS which provides this out of the box, even when transpiling only with TypeScript and not Babel.
TypeScript defaults allowSyntheticDefaultImports
to true
when targeting the System.register module format but the flag exists as a separate setting for those targeting different formats who would like to take advantage of the behavior.
from babel-plugin-dynamic-import-webpack.
Related Issues (20)
- Minimal sample code snippet using `import()` or link to spec
- Error handling HOT 8
- An in-range update of babel-cli is breaking the build 🚨 HOT 5
- An in-range update of eslint is breaking the build 🚨 HOT 1
- add chunk name HOT 1
- Default export is not picked up properly HOT 11
- add name to require.ensures HOT 7
- An in-range update of eslint-plugin-import is breaking the build 🚨 HOT 1
- An in-range update of babel-preset-airbnb is breaking the build 🚨 HOT 3
- Incompatible with lastest babel-core release HOT 1
- Unable to use import() with magic comments HOT 6
- An in-range update of eslint is breaking the build 🚨 HOT 2
- not work in webpack3 HOT 1
- Plugin Doesn't Work With babel-plugin-module-resolver HOT 5
- 1.0.2 breaks code splitting HOT 12
- Version 10 of node.js has been released
- An in-range update of babel-preset-airbnb is breaking the build 🚨 HOT 6
- Can I use it in React Native? HOT 1
- An in-range update of safe-publish-latest is breaking the build 🚨 HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from babel-plugin-dynamic-import-webpack.