├── .gitignore
├── .npmignore
├── test
├── bundle
│ ├── a.js
│ ├── c.js
│ ├── error.js
│ ├── b.js
│ ├── index.js
│ └── react-flow.js
├── pkg-app
│ ├── index.js
│ └── node_modules
│ │ └── app
│ │ ├── package.json
│ │ └── index.js
├── error.js
├── options.js
├── browserify-package.js
├── .swcrc
├── event.js
├── babel-source-maps.js
├── aaa.js
├── source-maps-absolute.js
├── source-maps-relative.js
├── browserify-cli.js
└── browser-pack-source-maps.js
├── .travis.yml
├── package.json
├── LICENSE
├── README.md
└── index.js
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .travis.yml
2 | test
3 |
--------------------------------------------------------------------------------
/test/bundle/a.js:
--------------------------------------------------------------------------------
1 | export default 'a is for apple';
2 |
--------------------------------------------------------------------------------
/test/pkg-app/index.js:
--------------------------------------------------------------------------------
1 | module.exports = require('app');
2 |
--------------------------------------------------------------------------------
/test/bundle/c.js:
--------------------------------------------------------------------------------
1 | module.exports = function() {
2 | return 'c';
3 | };
4 |
--------------------------------------------------------------------------------
/test/bundle/error.js:
--------------------------------------------------------------------------------
1 | class A {
2 | constructor () {
3 | super();
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/test/bundle/b.js:
--------------------------------------------------------------------------------
1 | export default () => ({
2 | catch: `catch`,
3 | delete: `delete`
4 | });
5 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 | language: node_js
3 | node_js:
4 | - "10"
5 | - "8"
6 | - "6"
7 |
--------------------------------------------------------------------------------
/test/bundle/index.js:
--------------------------------------------------------------------------------
1 | export {default as a} from './a';
2 | export {default as b} from './b';
3 | export {default as c} from './c';
4 |
--------------------------------------------------------------------------------
/test/pkg-app/node_modules/app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "browserify": {
3 | "transform": [
4 | "../../../../"
5 | ]
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/test/bundle/react-flow.js:
--------------------------------------------------------------------------------
1 | module.exports = (React) => {
2 | var TestComponent = React.createClass({
3 | envLength() {
4 | return process.env.NODE_ENV.length;
5 | },
6 | render() {
7 | return
;
8 | }
9 | });
10 | return TestComponent;
11 | }
12 |
--------------------------------------------------------------------------------
/test/pkg-app/node_modules/app/index.js:
--------------------------------------------------------------------------------
1 | module.exports = (React) => {
2 | var TestComponent = React.createClass({
3 | envLength() {
4 | return process.env.NODE_ENV.length;
5 | },
6 | render() {
7 | return ;
8 | }
9 | });
10 | return TestComponent;
11 | }
12 |
--------------------------------------------------------------------------------
/test/error.js:
--------------------------------------------------------------------------------
1 | var browserify = require('browserify');
2 | var path = require('path');
3 | var test = require('tape');
4 | var babelify = require('../');
5 |
6 | test('emits error', function(t) {
7 | t.plan(2);
8 |
9 | var b = browserify(path.join(__dirname, 'bundle/error.js'));
10 |
11 | b.transform(babelify.configure({}));
12 |
13 | b.bundle(function (err, src) {
14 | t.notOk(src);
15 | t.ok(err);
16 | });
17 | });
18 |
--------------------------------------------------------------------------------
/test/options.js:
--------------------------------------------------------------------------------
1 | var browserify = require('browserify');
2 | var test = require('tape');
3 | var path = require('path');
4 | var babelify = require('../');
5 |
6 | test('passes options via configure', function(t) {
7 | t.plan(3);
8 |
9 | var b = browserify(path.join(__dirname, 'bundle/index.js'));
10 |
11 | b.transform(babelify.configure({
12 | // plugins: ['@babel/plugin-transform-property-literals']
13 | }));
14 |
15 | b.bundle(function (err, src) {
16 | t.error(err);
17 | t.ok(src.toString().match(/'?catch'?: `catch`/));
18 | t.ok(src.toString().match(/'?delete'?: `delete`/));
19 | });
20 | });
21 |
--------------------------------------------------------------------------------
/test/browserify-package.js:
--------------------------------------------------------------------------------
1 | var browserify = require('browserify');
2 | var path = require('path');
3 | var test = require('tape');
4 | var vm = require('vm');
5 |
6 | test('browserify package', function (t) {
7 | t.plan(3);
8 |
9 | process.env.NODE_ENV = 'development';
10 |
11 | var b = browserify();
12 | b.require(path.join(__dirname, 'pkg-app/index.js'), {expose: 'pkgApp'});
13 |
14 | b.bundle(function (err, src) {
15 | t.error(err);
16 |
17 | var c = {};
18 | vm.runInNewContext(src, c);
19 |
20 | c.require('pkgApp')({
21 | createClass: function(obj) {
22 | t.equal(obj.envLength(), process.env.NODE_ENV.length);
23 | t.equal(obj.displayName, 'TestComponent')
24 | }
25 | });
26 | });
27 | });
28 |
--------------------------------------------------------------------------------
/test/.swcrc:
--------------------------------------------------------------------------------
1 | {
2 | "jsc": {
3 | "parser": {
4 | "syntax": "ecmascript",
5 | "jsx": true,
6 | "numericSeparator": false,
7 | "classPrivateProperty": false,
8 | "privateMethod": false,
9 | "classProperty": true,
10 | "functionBind": false,
11 | "decorators": false,
12 | "decoratorsBeforeExport": false
13 | },
14 | "transform": {
15 | "react": {
16 | "pragma": "React.createElement",
17 | "pragmaFrag": "React.Fragment",
18 | "throwIfNamespace": true,
19 | "development": true,
20 | "useBuiltins": true
21 | },
22 | "optimizer": {
23 | "globals": {
24 | "vars": {
25 | "__DEBUG__": "true"
26 | }
27 | }
28 | }
29 | }
30 | },
31 | "module": {
32 | "type": "commonjs",
33 | "strict": false,
34 | "strictMode": true,
35 | "lazy": false,
36 | "noInterop": false
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/test/event.js:
--------------------------------------------------------------------------------
1 | var browserify = require('browserify');
2 | var path = require('path');
3 | var test = require('tape');
4 | var swcify = require('../');
5 |
6 | var files = [
7 | path.join(__dirname, 'bundle/a.js'),
8 | path.join(__dirname, 'bundle/b.js'),
9 | path.join(__dirname, 'bundle/c.js'),
10 | path.join(__dirname, 'bundle/index.js')
11 | ];
12 |
13 | test('event', function (t) {
14 | t.plan(7);
15 |
16 | var swcified = [];
17 |
18 | var b = browserify(path.join(__dirname, 'bundle/index.js'));
19 | b.transform([swcify, {}]);
20 |
21 | b.on('transform', function(tr) {
22 | if (tr instanceof swcify) {
23 | tr.once('swcify', function(result, filename) {
24 | swcified.push(filename);
25 | t.equal(typeof result.code, 'string');
26 | });
27 | }
28 | });
29 |
30 | b.bundle(function (err, src) {
31 | t.error(err);
32 | t.ok(src);
33 | t.deepEqual(swcified.sort(), files);
34 | });
35 | });
36 |
--------------------------------------------------------------------------------
/test/babel-source-maps.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 | var swc = require('@swc/core');
3 | var convert = require('convert-source-map');
4 | var fs = require('fs');
5 | var path = require('path');
6 | var test = require('tape');
7 |
8 | // Validate assumptions about swc's source maps.
9 |
10 | var sourceFile = path.join(__dirname, 'bundle/index.js');
11 | assert(path.isAbsolute(sourceFile));
12 |
13 | var sourceSrc = fs.readFileSync(sourceFile, 'utf8');
14 |
15 | test('swc source maps (filename and sourceFileName)', function(t) {
16 | var result = swc.transformSync(sourceSrc, {
17 | sourceMaps: 'inline',
18 | filename: sourceFile,
19 | sourceFileName: sourceFile,
20 | });
21 |
22 | // With "sourceFileName", the source path is "sourceFileName".
23 | var sm = convert
24 | .fromJSON(result.map)
25 | // .fromSource(result.code.toString())
26 | .toObject();
27 |
28 | t.deepEqual(sm.sources, [sourceFile]);
29 |
30 | t.end();
31 | });
32 |
--------------------------------------------------------------------------------
/test/aaa.js:
--------------------------------------------------------------------------------
1 | var browserify = require('browserify');
2 | var test = require('tape');
3 | var path = require('path');
4 | var vm = require('vm');
5 | var swcify = require('../');
6 |
7 | test('aaa', function (t) {
8 | t.plan(2);
9 |
10 | var b = browserify();
11 |
12 | b.require(path.join(__dirname, 'bundle/index.js'), {expose: 'bundle'});
13 | b.transform([swcify]);
14 |
15 | b.bundle(function (err, src) {
16 | t.error(err);
17 | var c = {};
18 | vm.runInNewContext(src, c);
19 |
20 | t.equal(c.require('bundle').a, 'a is for apple');
21 | });
22 | });
23 |
24 | test('basedir', function (t) {
25 | t.plan(2);
26 |
27 | var b = browserify({basedir: __dirname});
28 |
29 | b.require(path.join(__dirname, 'bundle/index.js'), {expose: 'bundle'});
30 | b.transform([swcify]);
31 |
32 | b.bundle(function (err, src) {
33 | t.error(err);
34 | var c = {};
35 | vm.runInNewContext(src, c);
36 |
37 | t.equal(c.require('bundle').a, 'a is for apple');
38 | });
39 | })
40 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "swcify",
3 | "description": "SWC browserify transform",
4 | "version": "1.0.1",
5 | "author": "Dmitry Yvanov ",
6 | "license": "MIT",
7 | "homepage": "https://github.com/swc-project/swcify",
8 | "engines": {
9 | "node": ">=6.9.0"
10 | },
11 | "repository": {
12 | "type": "git",
13 | "url": "https://github.com/swc-project/swcify.git"
14 | },
15 | "bugs": {
16 | "url": "https://github.com/swc-project/swcify/issues"
17 | },
18 | "peerDependencies": {
19 | "@swc/core": "^1.0.25"
20 | },
21 | "devDependencies": {
22 | "@babel/core": "^7.3.4",
23 | "@swc/core": "^1.0.28",
24 | "browserify": "^16.2.3",
25 | "convert-source-map": "^1.5.1",
26 | "cross-spawn": "^6.0.5",
27 | "lodash.zipobject": "^4.1.3",
28 | "tape": "^4.10.1"
29 | },
30 | "scripts": {
31 | "test": "tape test/*.js"
32 | },
33 | "dependencies": {
34 | "inline-source-map-comment": "^1.0.5",
35 | "source-map-to-comment": "^1.1.0"
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2019 Dmitry Ivanov
2 |
3 | MIT License
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining
6 | a copy of this software and associated documentation files (the
7 | "Software"), to deal in the Software without restriction, including
8 | without limitation the rights to use, copy, modify, merge, publish,
9 | distribute, sublicense, and/or sell copies of the Software, and to
10 | permit persons to whom the Software is furnished to do so, subject to
11 | the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be
14 | included in all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/test/source-maps-absolute.js:
--------------------------------------------------------------------------------
1 | var browserify = require('browserify');
2 | var convert = require('convert-source-map');
3 | var path = require('path');
4 | var fs = require('fs');
5 | var zipObject = require('lodash.zipobject');
6 | var test = require('tape');
7 | var babelify = require('../');
8 |
9 | var sources = [
10 | path.join(__dirname, 'bundle/index.js'),
11 | path.join(__dirname, 'bundle/a.js'),
12 | path.join(__dirname, 'bundle/b.js'),
13 | path.join(__dirname, 'bundle/c.js')
14 | ].reduce(function(acc, file) {
15 | acc[file] = fs.readFileSync(file, 'utf8');
16 | return acc;
17 | }, {});
18 |
19 | test.skip('sourceMapsAbsolute', function(t) {
20 | t.plan(2);
21 |
22 | var b = browserify({
23 | entries: [path.join(__dirname, 'bundle/index.js')],
24 | debug: true
25 | });
26 |
27 | b.transform(babelify.configure({
28 | // presets: ['@babel/preset-env'],
29 | // sourceMapsAbsolute: true
30 | }));
31 |
32 | b.bundle(function (err, src) {
33 | t.error(err);
34 |
35 | var sm = convert
36 | .fromSource(src.toString())
37 | .toObject();
38 |
39 | // remove the prelude
40 | sm.sources.shift();
41 | sm.sourcesContent.shift();
42 |
43 | t.match(zipObject(sm.sources, sm.sourcesContent), sources);
44 | });
45 | });
46 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # swcify [](https://travis-ci.org/dy/swcify)
2 |
3 | [SWC](https://github.com/swc-project/swc) [browserify](https://github.com/substack/node-browserify) transform. Enables ES6/JSX/react for browserify times faster than babelify.
4 |
5 | ## Installation
6 |
7 | ```sh
8 | $ npm install --save-dev swcify @swc/core
9 | ```
10 |
11 | ## Usage
12 |
13 | ### CLI
14 |
15 | ```sh
16 | $ browserify script.js -t swcify > bundle.js
17 | ```
18 |
19 | By default, swcify reads `.swcrc` file in the basedir with SWC config.
20 |
21 | ### Node
22 |
23 | ```javascript
24 | var fs = require("fs")
25 | var browserify = require("browserify")
26 |
27 | var b = browserify("./script.js")
28 | .transform("swcify", config)
29 | .bundle()
30 | .pipe(fs.createWriteStream("bundle.js"));
31 | ```
32 |
33 | The optional argument `config` can be an object with options for SWC.
34 |
35 |
36 | ## FAQ
37 |
38 | ### Why aren't files in `node_modules` being transformed?
39 |
40 | This is the default browserify behavior.
41 |
42 | A possible solution is to add:
43 |
44 | ```json
45 | {
46 | "browserify": {
47 | "transform": ["swcify"]
48 | }
49 | }
50 | ```
51 |
52 | to the root of all your modules `package.json` that you want to be transformed.
53 |
54 |
55 | ### Why am I not getting source maps?
56 |
57 | To use source maps, enable them in browserify with the [`debug`](https://github.com/substack/node-browserify#browserifyfiles--opts) option:
58 |
59 | ```js
60 | browserify({debug: true}).transform("swcify");
61 | ```
62 |
63 | ```sh
64 | $ browserify -d -t swcify
65 | ```
66 |
--------------------------------------------------------------------------------
/test/source-maps-relative.js:
--------------------------------------------------------------------------------
1 | var browserify = require('browserify');
2 | var convert = require('convert-source-map');
3 | var fs = require('fs');
4 | var path = require('path');
5 | var zipObject = require('lodash.zipobject');
6 | var test = require('tape');
7 | var swcify = require('../');
8 |
9 | process.chdir(path.join(__dirname, '..'));
10 |
11 | var sources = [
12 | path.join(__dirname, 'bundle/index.js'),
13 | path.join(__dirname, 'bundle/a.js'),
14 | path.join(__dirname, 'bundle/b.js'),
15 | path.join(__dirname, 'bundle/c.js')
16 | ].reduce(function(acc, file) {
17 | acc[file] = fs.readFileSync(file, 'utf8');
18 | return acc;
19 | }, {});
20 |
21 | test.skip('source maps relative (cwd)', function(t) {
22 | t.plan(2);
23 |
24 | var b = browserify({
25 | entries: [path.join(__dirname, 'bundle/index.js')],
26 | debug: true
27 | });
28 |
29 | b.transform(swcify.configure({
30 | //presets: ['@babel/preset-env']
31 | }));
32 |
33 | b.bundle(function(err, src) {
34 | t.error(err);
35 |
36 | var sm = convert
37 | .fromSource(src.toString())
38 | .toObject();
39 |
40 | // remove the prelude
41 | sm.sources.shift();
42 | sm.sourcesContent.shift();
43 |
44 | var actual = zipObject(sm.sources, sm.sourcesContent);
45 |
46 | var expected = Object.keys(sources).reduce(function(acc, file) {
47 | acc[path.relative(process.cwd(), file)] = sources[file];
48 | return acc;
49 | }, {});
50 | t.equal(actual, expected);
51 | });
52 | });
53 |
54 | test.skip('source maps relative (basedir)', function(t) {
55 | t.plan(2);
56 |
57 | var b = browserify({
58 | entries: [path.join(__dirname, 'bundle/index.js')],
59 | basedir: __dirname,
60 | debug: true
61 | });
62 |
63 | b.transform(swcify.configure({
64 | presets: ['@babel/preset-env']
65 | }));
66 |
67 | b.bundle(function(err, src) {
68 | t.error(err);
69 |
70 | var sm = convert
71 | .fromSource(src.toString())
72 | .toObject();
73 |
74 | // remove the prelude
75 | sm.sources.shift();
76 | sm.sourcesContent.shift();
77 |
78 | var actual = zipObject(sm.sources, sm.sourcesContent);
79 |
80 | var expected = Object.keys(sources).reduce(function(acc, file) {
81 | acc[path.relative(__dirname, file)] = sources[file];
82 | return acc;
83 | }, {});
84 |
85 | t.match(actual, expected);
86 | });
87 | });
88 |
--------------------------------------------------------------------------------
/test/browserify-cli.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var spawn = require('cross-spawn');
3 | var test = require('tape');
4 | var vm = require('vm');
5 |
6 | test('browserify-cli no subargs', function (t) {
7 | t.plan(5);
8 |
9 | var cmd = require.resolve('browserify/bin/cmd.js');
10 | var args = [
11 | '-r', path.join(__dirname, '/bundle/index.js') + ':bundle',
12 | '-t', path.join(__dirname, '../')
13 | ];
14 |
15 | var out = '';
16 | var err = '';
17 |
18 | var ps = spawn(cmd, args);
19 | ps.stdout.on('data', function(buf) { out += buf; });
20 | ps.stderr.on('data', function(buf) { err += buf; });
21 |
22 | ps.on('error', function(err) { throw err; });
23 | ps.on('exit', function(code) {
24 | t.notOk(err);
25 | t.equal(code, 0);
26 |
27 | var c = {};
28 | vm.runInNewContext(out, c);
29 |
30 | t.equal(c.require('bundle').a, 'a is for apple');
31 | t.ok(out.toString().match(/'?catch'?: `catch`/));
32 | t.ok(out.toString().match(/'?delete'?: `delete`/));
33 | });
34 | });
35 |
36 | test.skip('browserify-cli with subargs', function (t) {
37 | // FIXME: react-flow is not supported for now
38 |
39 | t.plan(4);
40 |
41 | process.env.NODE_ENV = 'development';
42 |
43 | var cmd = require.resolve('browserify/bin/cmd.js');
44 | var args = [
45 | '-r', path.join(__dirname, '/bundle/react-flow.js') + ':reactFlow',
46 | '-t', '[',
47 | path.join(__dirname, '../'),
48 | // '--presets', '[', '@swc/preset-env', '@swc/preset-react', '@swc/preset-flow', ']',
49 | // '--plugins', '[',
50 | // '@swc/plugin-transform-react-display-name',
51 | // 'transform-node-env-inline',
52 | // ']',
53 | // '--config=123',
54 | ']'
55 | ];
56 |
57 | var out = '';
58 | var err = '';
59 |
60 | var ps = spawn(cmd, args);
61 | ps.stdout.on('data', function(buf) { console.log(buf.toString()); out += buf; });
62 | ps.stderr.on('data', function(buf) { err += buf; });
63 |
64 | ps.on('error', function(err) {throw err; });
65 | ps.on('exit', function(code) {
66 | console.log(err)
67 | t.notOk(err);
68 | t.equal(code, 0);
69 |
70 | var c = {};
71 | vm.runInNewContext(out, c);
72 |
73 | c.require('reactFlow')({
74 | createClass: function(obj) {
75 | t.equal(obj.envLength(), process.env.NODE_ENV.length);
76 | t.equal(obj.displayName, 'TestComponent');
77 | }
78 | });
79 | });
80 | });
81 |
--------------------------------------------------------------------------------
/test/browser-pack-source-maps.js:
--------------------------------------------------------------------------------
1 | var browserify = require('browserify');
2 | var convert = require('convert-source-map');
3 | var path = require('path');
4 | var zipObject = require('lodash.zipobject');
5 | var test = require('tape');
6 | var swcify = require('../');
7 |
8 | // Validate assumptions about browserify's browser-pack source maps. Without
9 | // intermediate source maps, the source is a relative path from the "basedir".
10 | // When "basedir" is not set, it's `process.cwd()`.
11 |
12 | test('browserify source maps (no basedir)', function(t) {
13 | t.plan(14);
14 |
15 | // normalize cwd
16 | process.chdir(path.join(__dirname, '..'));
17 |
18 | var b = browserify({
19 | entries: [path.join(__dirname, 'bundle/index.js')],
20 | debug: true
21 | });
22 |
23 | b.transform(swcify, {
24 | // presets: ['@babel/preset-env'],
25 | sourceMaps: false // no intermediate source maps
26 | });
27 |
28 | var deps = {};
29 | b.on('dep', function(dep) {
30 | t.ok(path.isAbsolute(dep.file));
31 | deps[dep.file] = dep.source;
32 | });
33 |
34 | b.bundle(function (err, src) {
35 | t.error(err);
36 |
37 | var sm = convert
38 | .fromSource(src.toString())
39 | .toObject();
40 |
41 | // remove the prelude
42 | sm.sources.shift();
43 | sm.sourcesContent.shift();
44 |
45 | // source paths are relative to the basedir (cwd if not set)
46 | sm.sources.forEach(function(source) {
47 | t.ok(!path.isAbsolute(source));
48 | var aSource = path.join(__dirname, '..', source);
49 | t.ok(deps.hasOwnProperty(aSource));
50 | });
51 |
52 | var smDeps = zipObject(
53 | sm.sources.map(function(x) { return path.join(__dirname, '..', x); }),
54 | sm.sourcesContent
55 | );
56 |
57 | t.deepEqual(sort(smDeps), sort(deps));
58 | });
59 | });
60 |
61 | test('browserify source maps (with basedir)', function(t) {
62 | t.plan(14);
63 |
64 | // normalize cwd
65 | process.chdir(path.join(__dirname, '..'));
66 |
67 | var b = browserify({
68 | entries: [path.join(__dirname, 'bundle/index.js')],
69 | basedir: __dirname,
70 | debug: true
71 | });
72 |
73 | b.transform(swcify, {
74 | // presets: ['@babel/preset-env'],
75 | sourceMaps: false // no intermediate source maps
76 | });
77 |
78 | var deps = {};
79 | b.on('dep', function(dep) {
80 | t.ok(path.isAbsolute(dep.file));
81 | deps[dep.file] = dep.source;
82 | });
83 |
84 | b.bundle(function (err, src) {
85 | t.error(err);
86 |
87 | var sm = convert
88 | .fromSource(src.toString())
89 | .toObject();
90 |
91 | // remove the prelude
92 | sm.sources.shift();
93 | sm.sourcesContent.shift();
94 |
95 | // source paths are relative to the basedir (cwd if not set)
96 | sm.sources.forEach(function(source) {
97 | t.ok(!path.isAbsolute(source));
98 | var aSource = path.join(__dirname, source);
99 | t.ok(deps.hasOwnProperty(aSource));
100 | });
101 |
102 | var smDeps = zipObject(
103 | sm.sources.map(function(x) { return path.join(__dirname, x); }),
104 | sm.sourcesContent
105 | );
106 |
107 | t.deepEqual(sort(smDeps), sort(deps));
108 | });
109 | });
110 |
111 | function sort(obj) {
112 | return Object.keys(obj).sort().reduce(function(acc, k) {
113 | acc[k] = obj[k];
114 | return acc;
115 | }, {});
116 | }
117 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | var stream = require("stream");
4 | var util = require("util");
5 | var path = require("path");
6 | var swc = require("@swc/core");
7 | var fs = require("fs");
8 | var inlineSourcemap = require('inline-source-map-comment')
9 |
10 | var defaults = {
11 | "jsc": {
12 | "parser": {
13 | "syntax": "ecmascript",
14 | "jsx": true,
15 | "numericSeparator": false,
16 | "classPrivateProperty": true,
17 | "privateMethod": false,
18 | "classProperty": true,
19 | "functionBind": false,
20 | "decorators": false,
21 | "decoratorsBeforeExport": false
22 | },
23 | "target": "es2016",
24 | "transform": {
25 | "react": {
26 | "pragma": "React.createElement",
27 | "pragmaFrag": "React.Fragment",
28 | "throwIfNamespace": true,
29 | "development": false,
30 | "useBuiltins": false
31 | },
32 | "optimizer": {
33 | "globals": {
34 | "vars": {
35 | "__DEBUG__": "true"
36 | }
37 | }
38 | }
39 | }
40 | },
41 | "module": {
42 | "type": "commonjs",
43 | "strict": false,
44 | "strictMode": true,
45 | "lazy": false,
46 | "noInterop": false
47 | }
48 | }
49 |
50 | module.exports = buildTransform();
51 | module.exports.defaults = defaults;
52 | module.exports.configure = buildTransform;
53 |
54 |
55 | // TODO: essentially we have to handle all CLI-tool options
56 | // some of them are taken from browserify flags
57 |
58 | // Allow projects to import this module and check `foo instanceof swcify`
59 | // to see if the current stream they are working with is one created
60 | // by SWCify.
61 | Object.defineProperty(module.exports, Symbol.hasInstance, {
62 | value: function hasInstance(obj) {
63 | return obj instanceof SwcifyStream;
64 | },
65 | });
66 |
67 | function buildTransform(opts) {
68 | var configCache = {}
69 |
70 | return function (filename, config) {
71 |
72 | var _flags = config._flags || {}
73 | config = Object.assign({}, config)
74 | delete config._flags
75 |
76 | // unwrap nested config
77 | if (config.config) {
78 | config = config
79 | }
80 |
81 | var basedir = path.resolve(_flags.basedir || ".");
82 | var configPath = path.resolve(basedir, '.swcrc');
83 |
84 | var configJSON, parsedConfig = configCache[configPath];
85 |
86 | // if no cached config found - try to read from file
87 | if (!parsedConfig && fs.existsSync(configPath)) {
88 | // read filepath config
89 | // read .swcrc relative to basedir
90 | // Browserify doesn't actually always normalize the filename passed
91 | // to transforms, so we manually ensure that the filename is relative
92 | configJSON = fs.readFileSync(configPath, 'utf-8');
93 | // bad config will throw error
94 | parsedConfig = JSON.parse(configJSON)
95 | configCache[configPath] = parsedConfig
96 | }
97 |
98 | // no config found, falling back to default options
99 | // create current config from options extended with the config
100 | config = Object.assign({
101 | sourceMaps: _flags.debug
102 | }, defaults, opts, parsedConfig, config)
103 |
104 | // normalize config quirks
105 | if (!config.sourceMaps) delete config.sourceMaps
106 |
107 | return new SwcifyStream({
108 | config: config,
109 | filename: path.resolve(basedir, filename)
110 | });
111 | };
112 | }
113 |
114 | class SwcifyStream extends stream.Transform {
115 | constructor(opts) {
116 | super();
117 | this._code = [];
118 | this._sourceMap = [];
119 | if (!opts) opts = {}
120 | this._opts = opts;
121 | }
122 |
123 | _transform(buf, enc, callback) {
124 | var self = this
125 | swc.transform(buf.toString(), this._opts.config).then(function(result) {
126 | var code = result !== null ? result.code : data;
127 |
128 | if (result.map) {
129 | code += inlineSourcemap(result.map)
130 | }
131 | self.push(code);
132 | self._code.push(code);
133 | self._sourceMap.push(result && result.map)
134 | callback();
135 | }, callback)
136 | }
137 |
138 | _flush(callback) {
139 | // Merge the buffer pieces after all are available, instead of one at a time,
140 | // to avoid corrupting multibyte characters.
141 | this.emit("swcify", {
142 | code: this._code.join('')
143 | // FIXME: how to join sourcemaps
144 | }, this._opts.filename);
145 | callback()
146 | }
147 | }
148 |
--------------------------------------------------------------------------------