shapesecurity / bandolier Goto Github PK
View Code? Open in Web Editor NEWBandolier - bundler for ES2017 modules
License: Apache License 2.0
Bandolier - bundler for ES2017 modules
License: Apache License 2.0
The import assignment resolver fails to see generated module names as different from function locals of the same name, leading to runtime or compile-time errors being thrown for assignment to an import, when no such assignment happened.
Hi,
I derived the project into a maven plugin.
this is just a test
<plugin>
<groupId>com.shapesecurity</groupId>
<artifactId>shift-ast-maven-plugin</artifactId>
<version>1.0.0-SNAPSHOT</version>
<configuration>
<inputDirectory>src/main/scripts</inputDirectory>
<outputFile>target/runnable.js</outputFile>
</configuration>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
but I believe that the tools proposed by shift-ast shook welcome as maven plugins.
You will find my code here
https://github.com/sekaijin/shift-ast-maven-plugin
A+JYT
Given the modules:
// circular1.js
import circ2 from '/root/circular1_dep.js';
export var exportedResult = circ2 + 5;
var result = exportedResult;
//circular1_dep.js
export default 7;
import {exportedResult as circ1} from '/root/circular1.js';
The standard bundler does not provide the correct output of 12 for the value of result
, as expected by the spec, or other implementations.
Module piercing does not have this issue.
If there are two modules in the graph with identical ASTs, bandolier will not build the graph. For example:
./bin/bandolier.sh a.js
// a.js
import './b.js';
import './c.js';
// b.js
console.log(0);
// c.js
console.log(0);
results in
Exception in thread "main" com.shapesecurity.bandolier.es2017.loader.ModuleLoaderException: Module Loader Exception: module /bandolier/a.js cannot be loaded: Not all modules were scheduled: 2 / 3.
Unscheduled modules:
at com.shapesecurity.bandolier.es2017.Bundler.bundleString(Bundler.java:115)
at com.shapesecurity.bandolier.es2017.Bundler.bundle(Bundler.java:79)
at com.shapesecurity.bandolier.es2017.Main.main(Main.java:48)
Caused by: java.lang.RuntimeException: Not all modules were scheduled: 2 / 3.
Unscheduled modules:
at com.shapesecurity.bandolier.es2017.transformations.ImportExportConnector.combineModules(ImportExportConnector.java:463)
at com.shapesecurity.bandolier.es2017.bundlers.PiercedModuleBundler.bundleEntrypoint(PiercedModuleBundler.java:47)
at com.shapesecurity.bandolier.es2017.Bundler.bundleString(Bundler.java:113)
... 2 more
Suppose we have
a.js
:
export function thing() {
return 42;
}
b.js
:
import { thing as other } from './a.js';
window.x = function () {
return function thing() {
other();
};
};
Running bandolier
with default options and passing b.js
as the entrypoint produces
(function(e) {
'use strict';
window.x = function() {
return function thing() {
thing();
};
};
var t = { __proto__: null };
if (e.Symbol) e.Object.defineProperty(t, e.Symbol.toStringTag, { value: 'Module' });
t = e.Object.freeze(t);
return t;
})(this);
That's wrong: thing
should not call itself, it should call the function which returns 42.
Presumably because of iteration over a HashMap.
I like reproducible builds, so this makes me sad.
Latest version of closure compiler can aggregate files very similarly, I wonder if there is any considerable differences considering that closure compiler is somewhat slow and very convoluted to set up correctly.
Current FileLoader
does not have a fallback option (unlike the MapResourceLoader
). This is needed if we want to chain file loaders.
If we're going to have a package.json
, CI should require it to be in sync with pom.xml
(and both should get published at the same time).
This was recently added into the language. See tc39/ecma262#2154.
Consider the following program:
function a() {}
function b() { return a(); }
var c = 0;
var d = 1;
export { d };
If you run bandolier with that as the entrypoint, with default options, you get (an unformatted version of)
(function(w) {
'use strict';
function a() {}
var d = 1;
var e = { __proto__: null, d: d };
if (w.Symbol)
w.Object.defineProperty(e, w.Symbol.toStringTag, { value: 'Module' });
e = w.Object.freeze(e);
return e;
})(this);
As you'd expect, b
and c
are eliminated. But a
is not. This is presumably because it's only dead after b
has been eliminated.
I think dead code elimination should be run to a fixpoint, so that a
is removed as well.
Currently, if a module or any dependency uses require
or module.exports
, Bandolier will fail to successfully bundle the script. We could resolve this with an unsafe translation to import/export. The primary side effect is the dependency modules will be executed before the depending module is executed, rather than during it.
running
./bin/bandolier.sh a.js
with
// a.mjs
import './b.mjs';
import './c.mjs';
// b.mjs
console.log(0);
// c.mjs
console.log(1);
results in
(function (_r) {
"use strict";
console.log(1);
console.log(0);
var _u = { __proto__: null };
if (_r.Symbol)
_r.Object.defineProperty(_u, _r.Symbol.toStringTag, { value: "Module" });
_u = _r.Object.freeze(_u);
return _u;
})(this);
which logs 1 before 0.
It should be the other way around.
For example,
export default class {}
generates code which exports a class whose .name
is q
.
That's probably fine, but should be documented.
Module a
:
export default 0;
Module b
:
export * from 'a';
Module c
:
import * as a from 'a';
import * as b from 'b';
assert(a.default === b.default);
The program
export default class {}
with default options and using StandardModuleBundler
generates a "program" containing
(function(global) {
// ...
require.define('1', function(module, exports, __dirname, __filename) {
class {}
exports['default'] = *default*;
});
return require('1');
}.call(this, this));
Note the class declaration without a name, and non-expression following exports['default'] =
.
At present, one of many ambiguous proxy-export-sourced exports will be exported, while they should throw an error.
It leads to the gross imperative patterns you see in Bundler.loadDependencies
and Bundler.bundleString
.
shape-functional-java already provides ImmutableListAppend<T>
, and this should be used in its place.
Given the modules:
// renaming.js
import {x, setX} from '/root/renaming_dep.js';
var tempX = x;
setX(10);
var result = tempX + x;
//renaming_dep.js
export var x = 5;
export function setX(y) {
x = y;
}
The standard bundler does not provide the correct output of 15 for the value of result
in renaming.js
, as expected by the spec, or other implementations.
Module piercing does not have this issue.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.