thheller / shadow-cljs

ClojureScript compilation made easy
https://github.com/thheller/shadow-cljs
Eclipse Public License 1.0
2.25k stars 178 forks source link

npm-module exports vars in random order with large namespaces #1171

Closed lilactown closed 7 months ago

lilactown commented 7 months ago

weird bug find: when using :npm-module and I have a namespace with more than 8 definitions, the Object.defineProperty(module.exports, ...) are output in random order.

For instance, given the file:

(ns town.lilac.npm-module-bug)
(def ^:export A)
(def ^:export B)
(def C)
(def D)
(def E)
(def F)
(def G)
(def H)
(def ^:export I)

This outputs the following javascript:

var $CLJS = require("./cljs_env");
var $jscomp = $CLJS.$jscomp;
var COMPILED = false;
require("./cljs.core.js");
var cljs=$CLJS.cljs || ($CLJS.cljs = {});
var town=$CLJS.town || ($CLJS.town = {});
var goog=$CLJS.goog || ($CLJS.goog = {});

$CLJS.SHADOW_ENV.setLoaded("town.lilac.npm_module_bug.js");

goog.provide('town.lilac.npm_module_bug');
Object.defineProperty(module.exports, "I", { enumerable: true, get: function() { return town.lilac.npm_module_bug.I; } });
Object.defineProperty(module.exports, "A", { enumerable: true, get: function() { return town.lilac.npm_module_bug.A; } });
Object.defineProperty(module.exports, "B", { enumerable: true, get: function() { return town.lilac.npm_module_bug.B; } });
//# sourceMappingURL=town.lilac.npm_module_bug.js.map

This is problematic for things like storybook, where each individual story is created via an exported var in a module; Storybook shows the stories in the order in which they are iterated over in the `module.exports, and given the current compiler behavior there's no way for us to directly control the order in which they appear from CLJS.

thheller commented 7 months ago

Nothing weird about it really. It takes the analyzer defs map, which on smaller namespaces will be an array map, so order preserving. Larger will eventually switch to hash map and thus end up "random".

I guess it could sort by source line metadata or so, not something that has come up before.

lilactown commented 7 months ago

thank you!