bun icon indicating copy to clipboard operation
bun copied to clipboard

`ReferenceError` on a bundle made by `rollup`

Open coderaiser opened this issue 3 years ago • 6 comments

I made a bundle of 🐊Putout that works on node.js and deno, but when I run with bun, I have an error:

coderaiser@localcmd:~/putout-bundle$ bun bundle/putout.js
58736 | 		        .build("expression")
58737 | 		        .field("expression", def("Expression"));
58738 | 		}
58739 | 		exports.default = default_1;
58740 | 		module.exports = exports["default"];
58741 | } (jsx, jsx.exports));
      ^
 ReferenceError: Can't find variable: jsx
      at requireJsx (/Users/coderaiser/putout-bundle/bundle/putout.js:58741:3)
      at /Users/coderaiser/putout-bundle/bundle/putout.js:59884:43
      at requireMain (/Users/coderaiser/putout-bundle/bundle/putout.js:59920:42)
      at /Users/coderaiser/putout-bundle/bundle/putout.js:76015:34
      at /Users/coderaiser/putout-bundle/bundle/putout.js:76073:6

When I extracted this function into a file jsx.js:

var jsx = {exports: {}};

var hasRequiredJsx;

function requireJsx () {
	if (hasRequiredJsx) return jsx.exports;
	hasRequiredJsx = 1;
	(function (module, exports) {
		Object.defineProperty(exports, "__esModule", { value: true });
		var tslib_1 = require$$0$8;
		var es_proposals_1 = (0, tslib_1.__importDefault)(requireEsProposals());
		var types_1 = (0, tslib_1.__importDefault)(requireTypes());
		var shared_1 = (0, tslib_1.__importDefault)(requireShared());
		function default_1(fork) {
		    fork.use(es_proposals_1.default);
		    var types = fork.use(types_1.default);
		    var def = types.Type.def;
		    var or = types.Type.or;
		    var defaults = fork.use(shared_1.default).defaults;
		    def("JSXAttribute")
		        .bases("Node")
		        .build("name", "value")
		        .field("name", or(def("JSXIdentifier"), def("JSXNamespacedName")))
		        .field("value", or(def("Literal"), // attr="value"
		    def("JSXExpressionContainer"), // attr={value}
		    def("JSXElement"), // attr=<div />
		    def("JSXFragment"), // attr=<></>
		    null // attr= or just attr
		    ), defaults["null"]);
		    def("JSXIdentifier")
		        .bases("Identifier")
		        .build("name")
		        .field("name", String);
		    def("JSXNamespacedName")
		        .bases("Node")
		        .build("namespace", "name")
		        .field("namespace", def("JSXIdentifier"))
		        .field("name", def("JSXIdentifier"));
		    def("JSXMemberExpression")
		        .bases("MemberExpression")
		        .build("object", "property")
		        .field("object", or(def("JSXIdentifier"), def("JSXMemberExpression")))
		        .field("property", def("JSXIdentifier"))
		        .field("computed", Boolean, defaults.false);
		    var JSXElementName = or(def("JSXIdentifier"), def("JSXNamespacedName"), def("JSXMemberExpression"));
		    def("JSXSpreadAttribute")
		        .bases("Node")
		        .build("argument")
		        .field("argument", def("Expression"));
		    var JSXAttributes = [or(def("JSXAttribute"), def("JSXSpreadAttribute"))];
		    def("JSXExpressionContainer")
		        .bases("Expression")
		        .build("expression")
		        .field("expression", or(def("Expression"), def("JSXEmptyExpression")));
		    var JSXChildren = [or(def("JSXText"), def("JSXExpressionContainer"), def("JSXSpreadChild"), def("JSXElement"), def("JSXFragment"), def("Literal") // Legacy: Esprima should return JSXText instead.
		        )];
		    def("JSXElement")
		        .bases("Expression")
		        .build("openingElement", "closingElement", "children")
		        .field("openingElement", def("JSXOpeningElement"))
		        .field("closingElement", or(def("JSXClosingElement"), null), defaults["null"])
		        .field("children", JSXChildren, defaults.emptyArray)
		        .field("name", JSXElementName, function () {
		        // Little-known fact: the `this` object inside a default function
		        // is none other than the partially-built object itself, and any
		        // fields initialized directly from builder function arguments
		        // (like openingElement, closingElement, and children) are
		        // guaranteed to be available.
		        return this.openingElement.name;
		    }, true) // hidden from traversal
		        .field("selfClosing", Boolean, function () {
		        return this.openingElement.selfClosing;
		    }, true) // hidden from traversal
		        .field("attributes", JSXAttributes, function () {
		        return this.openingElement.attributes;
		    }, true); // hidden from traversal
		    def("JSXOpeningElement")
		        .bases("Node")
		        .build("name", "attributes", "selfClosing")
		        .field("name", JSXElementName)
		        .field("attributes", JSXAttributes, defaults.emptyArray)
		        .field("selfClosing", Boolean, defaults["false"]);
		    def("JSXClosingElement")
		        .bases("Node")
		        .build("name")
		        .field("name", JSXElementName);
		    def("JSXFragment")
		        .bases("Expression")
		        .build("openingFragment", "closingFragment", "children")
		        .field("openingFragment", def("JSXOpeningFragment"))
		        .field("closingFragment", def("JSXClosingFragment"))
		        .field("children", JSXChildren, defaults.emptyArray);
		    def("JSXOpeningFragment")
		        .bases("Node")
		        .build();
		    def("JSXClosingFragment")
		        .bases("Node")
		        .build();
		    def("JSXText")
		        .bases("Literal")
		        .build("value", "raw")
		        .field("value", String)
		        .field("raw", String, function () {
		        return this.value;
		    });
		    def("JSXEmptyExpression")
		        .bases("Node")
		        .build();
		    def("JSXSpreadChild")
		        .bases("Node")
		        .build("expression")
		        .field("expression", def("Expression"));
		}
		exports.default = default_1;
		module.exports = exports["default"];
} (jsx, jsx.exports));
	return jsx.exports;
}

And run with bun jsx.js everything works fine, so maybe the reason is TO MANY VARIABLES in global scope, or something like this.

coderaiser avatar Jul 08 '22 08:07 coderaiser

This is probably a symbol collision issue in bun's transpiler

If you change the file extension to .mjs or .cjs, does it still happen? Bun enables the JSX transform by default in .js files, but does not in any of the other non-jsx file extensions

Jarred-Sumner avatar Jul 08 '22 08:07 Jarred-Sumner

Yes it works with .mjs extension!

Bun enables the JSX transform by default in .js files, but does not in any of the other non-jsx file extensions

The thing is there is no JSX syntax in the bundle, it has @babel/parser included to have ability to parse files, since 🐊Putout is a code transformer.

coderaiser avatar Jul 08 '22 10:07 coderaiser

I ran into the same error trying to use Pug which also imports Babel's parser.

Running...

import * as pug from 'pug'
let html = pug.compile('p Bun!')

... produces:

11657 |     throw error;
11658 |   }
11659 | }
11660 | const mixinPlugins = {
11661 |   estree,
11662 |   jsx,
      ^
 ReferenceError: Can't find variable: jsx
      at /Users/zolo/project/blog/node_modules/@babel/parser/lib/index.js:11662:2
      at bun:wrap:1:16430
      at /Users/zolo/project/blog/node_modules/constantinople/lib/index.js:3:23
      at bun:wrap:1:16430
      at /Users/zolo/project/blog/node_modules/pug-filters/lib/handle-filters.js:4:29
      at bun:wrap:1:16430
      at /Users/zolo/project/blog/node_modules/pug-filters/index.js:4:32
      at bun:wrap:1:16430
      at /Users/zolo/project/blog/node_modules/pug/lib/index.js:19:22
      at bun:wrap:1:16430
      at /Users/zolo/project/blog/server.ts:1:0

zolomatok avatar Jul 08 '22 22:07 zolomatok

Any progress on this?

coderaiser avatar Oct 14 '22 19:10 coderaiser

I'd also love an update on this.

zolomatok avatar Oct 24 '22 14:10 zolomatok

@coderaiser Seems to have been solved in one of the latest releases. I had the same problem with pug and I don't anymore.

zolomatok avatar Jan 12 '23 10:01 zolomatok