purus 0.8.1 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/purus-core.js CHANGED
@@ -12,6 +12,7 @@ const path = require("path");
12
12
 
13
13
  const COMPILER_JS = path.join(__dirname, "purus-compiler.js");
14
14
  const VERSION = require("../package.json").version;
15
+ const stdlib = require("./stdlib.js");
15
16
 
16
17
  /**
17
18
  * Compile Purus source code to JavaScript.
@@ -25,7 +26,7 @@ function compile(source, options = {}) {
25
26
  const { header = true, strict = true, type: moduleType } = options;
26
27
  const tmpFile = path.join(
27
28
  require("os").tmpdir(),
28
- `purus_${Date.now()}_${Math.random().toString(36).slice(2)}.purus`
29
+ `purus_${Date.now()}_${Math.random().toString(36).slice(2)}.purus`,
29
30
  );
30
31
  const fs = require("fs");
31
32
  try {
@@ -38,11 +39,12 @@ function compile(source, options = {}) {
38
39
  args.push("--type", "commonjs");
39
40
  }
40
41
  args.push(tmpFile);
41
- const result = execFileSync(process.execPath, [COMPILER_JS, ...args], {
42
+ let result = execFileSync(process.execPath, [COMPILER_JS, ...args], {
42
43
  encoding: "utf8",
43
44
  stdio: ["pipe", "pipe", "pipe"],
44
45
  timeout: 30000,
45
46
  });
47
+ result = stdlib.postProcess(result);
46
48
  if (header) {
47
49
  return `// Generated by Purus ${VERSION}\n${result}`;
48
50
  }
@@ -66,7 +68,7 @@ function compile(source, options = {}) {
66
68
  function check(source) {
67
69
  const tmpFile = path.join(
68
70
  require("os").tmpdir(),
69
- `purus_${Date.now()}_${Math.random().toString(36).slice(2)}.purus`
71
+ `purus_${Date.now()}_${Math.random().toString(36).slice(2)}.purus`,
70
72
  );
71
73
  const fs = require("fs");
72
74
  try {
@@ -17,7 +17,10 @@ for (let i = 0; i < args.length; i++) {
17
17
  if (args[i] === "--no-header") {
18
18
  noHeader = true;
19
19
  } else if (args[i] === "--strict") {
20
- if (i + 1 < args.length && (args[i + 1] === "true" || args[i + 1] === "false")) {
20
+ if (
21
+ i + 1 < args.length &&
22
+ (args[i + 1] === "true" || args[i + 1] === "false")
23
+ ) {
21
24
  strict = args[++i] === "true";
22
25
  } else {
23
26
  strict = true;
@@ -60,7 +63,11 @@ if (entry && fs.existsSync(entry) && fs.statSync(entry).isFile()) {
60
63
  const source = fs.readFileSync(entry, "utf8");
61
64
  const useStrict = strict !== null ? strict : true;
62
65
  const resolvedModule = resolveModuleType(entry, moduleType);
63
- const js = compile(source, { header: false, strict: useStrict, module: resolvedModule });
66
+ const js = compile(source, {
67
+ header: false,
68
+ strict: useStrict,
69
+ module: resolvedModule,
70
+ });
64
71
  const m = new (require("module"))();
65
72
  m._compile(js, entry);
66
73
  } else {
@@ -110,11 +117,15 @@ if (entry && fs.existsSync(entry) && fs.statSync(entry).isFile()) {
110
117
  const source = fs.readFileSync(f, "utf8");
111
118
  const useStrict2 = strict !== null ? strict : true;
112
119
  const resolvedModule = resolveModuleType(f, moduleType);
113
- const js = compile(source, { header: false, strict: useStrict2, module: resolvedModule });
120
+ const js = compile(source, {
121
+ header: false,
122
+ strict: useStrict2,
123
+ module: resolvedModule,
124
+ });
114
125
 
115
126
  const tmpFile = path.join(
116
127
  require("os").tmpdir(),
117
- `purus_run_${Date.now()}_${Math.random().toString(36).slice(2)}.js`
128
+ `purus_run_${Date.now()}_${Math.random().toString(36).slice(2)}.js`,
118
129
  );
119
130
  try {
120
131
  fs.writeFileSync(tmpFile, js, "utf8");
package/lib/stdlib.js ADDED
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Purus stdlib resolver — replaces codegen markers with actual JS from stdlib/*.js
3
+ *
4
+ * Marker emitted by the MoonBit compiler:
5
+ * // @purus-stdlib:whole:<module>:<binding>
6
+ *
7
+ * Tree-shaking: only properties actually referenced as `binding.xxx`
8
+ * in the rest of the code are included in the emitted object.
9
+ */
10
+
11
+ "use strict";
12
+
13
+ const fs = require("fs");
14
+ const path = require("path");
15
+
16
+ const STDLIB_DIR = path.join(__dirname, "..", "stdlib");
17
+ const cache = {};
18
+
19
+ // Global objects reachable by spread name
20
+ const GLOBALS = { Math, JSON };
21
+
22
+ /** Load and cache a stdlib module. */
23
+ function load(name) {
24
+ if (cache[name]) return cache[name];
25
+ const fp = path.join(STDLIB_DIR, name + ".js");
26
+ const src = fs.readFileSync(fp, "utf8");
27
+ const m = require(fp);
28
+ cache[name] = {
29
+ src,
30
+ mod: m.mod,
31
+ spread: m.spread || null,
32
+ spreadObj: m.spread ? GLOBALS[m.spread] || null : null,
33
+ constants: m.constants || {},
34
+ };
35
+ return cache[name];
36
+ }
37
+
38
+ /** Extract source of a single method from exports.mod block. */
39
+ function extractMethod(src, name) {
40
+ // Match: name( ... ) { ... } (balanced braces)
41
+ const re = new RegExp(`(?:^|[,\\n])\\s*(${name}\\([^)]*\\)\\s*\\{)`, "m");
42
+ const hit = re.exec(src);
43
+ if (!hit) return null;
44
+ const start = src.indexOf(hit[1], hit.index);
45
+ let depth = 0,
46
+ end = start;
47
+ let inBrace = false;
48
+ for (let i = start; i < src.length; i++) {
49
+ if (src[i] === "{") {
50
+ depth++;
51
+ inBrace = true;
52
+ }
53
+ if (src[i] === "}") depth--;
54
+ if (inBrace && depth === 0) {
55
+ end = i;
56
+ break;
57
+ }
58
+ }
59
+ return src.slice(start, end + 1);
60
+ }
61
+
62
+ /** Collect `this.xxx(` calls in a method body to find internal deps. */
63
+ function collectThisDeps(methodSrc) {
64
+ const deps = new Set();
65
+ for (const m of methodSrc.matchAll(/this\.(\w+)\s*\(/g)) deps.add(m[1]);
66
+ return deps;
67
+ }
68
+
69
+ /** Recursively collect all deps for a set of method names. */
70
+ function collectAllDeps(mod, src, names) {
71
+ const all = new Set(names);
72
+ const queue = [...names];
73
+ while (queue.length) {
74
+ const name = queue.pop();
75
+ if (typeof mod[name] !== "function") continue;
76
+ const body = extractMethod(src, name);
77
+ if (!body) continue;
78
+ for (const dep of collectThisDeps(body)) {
79
+ if (!all.has(dep) && dep in mod) {
80
+ all.add(dep);
81
+ queue.push(dep);
82
+ }
83
+ }
84
+ }
85
+ return all;
86
+ }
87
+
88
+ /**
89
+ * Resolve a whole-module import with tree-shaking.
90
+ * Scans `restOfCode` for `binding.xxx` to determine used properties.
91
+ */
92
+ function resolveWhole(moduleName, binding, restOfCode) {
93
+ const m = load(moduleName);
94
+
95
+ // Collect used property names
96
+ const re = new RegExp("\\b" + binding + "\\.(\\w+)\\b", "g");
97
+ const used = new Set();
98
+ for (const match of restOfCode.matchAll(re)) used.add(match[1]);
99
+
100
+ if (used.size === 0) return `const ${binding} = {};`;
101
+
102
+ // Expand with internal `this.xxx()` dependencies
103
+ const expanded = collectAllDeps(m.mod, m.src, used);
104
+
105
+ const props = [];
106
+
107
+ for (const name of expanded) {
108
+ // 1. constant alias (pi → Math.PI)
109
+ if (m.constants[name]) {
110
+ props.push(`${name}: ${m.spread}.${m.constants[name]}`);
111
+ continue;
112
+ }
113
+ // 2. spread member (abs → Math.abs)
114
+ if (m.spreadObj && name in m.spreadObj) {
115
+ props.push(`${name}: ${m.spread}.${name}`);
116
+ continue;
117
+ }
118
+ // 3. custom function — extract from source
119
+ if (typeof m.mod[name] === "function") {
120
+ const body = extractMethod(m.src, name);
121
+ if (body) {
122
+ props.push(body);
123
+ continue;
124
+ }
125
+ }
126
+ }
127
+
128
+ if (props.length === 0) return `const ${binding} = {};`;
129
+ if (props.length <= 3) return `const ${binding} = { ${props.join(", ")} };`;
130
+ return `const ${binding} = {\n ${props.join(",\n ")},\n};`;
131
+ }
132
+
133
+ /**
134
+ * Post-process compiler output: replace stdlib markers with actual JS.
135
+ */
136
+ function postProcess(js) {
137
+ return js.replace(
138
+ /^(\s*)\/\/ @purus-stdlib:whole:([\w-]+):([\w-]+)$/gm,
139
+ (match, indent, moduleName, binding) => {
140
+ // Everything after this marker is "rest of code" for tree-shaking
141
+ const markerEnd = js.indexOf(match) + match.length;
142
+ const rest = js.slice(markerEnd);
143
+ const code = resolveWhole(moduleName, binding, rest);
144
+ return code
145
+ .split("\n")
146
+ .map((l) => indent + l)
147
+ .join("\n");
148
+ },
149
+ );
150
+ }
151
+
152
+ module.exports = { postProcess, load };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "purus",
3
- "version": "0.8.1",
3
+ "version": "0.9.0",
4
4
  "description": "Purus - /ˈpuː.rus/ means pure✨ in Latin - is a beautiful, simple, and easy-to-use language. It compiles to JavaScript. It makes your fingers free from the Shift key. With Purus, you can write code almost without pressing the Shift key.",
5
5
  "main": "index.js",
6
6
  "module": "index.mjs",
@@ -21,14 +21,22 @@
21
21
  "index.d.ts",
22
22
  "bin/",
23
23
  "lib/",
24
+ "stdlib/",
24
25
  "LICENSE",
25
26
  "README.md",
26
27
  "README-ja.md"
27
28
  ],
28
29
  "scripts": {
30
+ "test": "moon test --target js",
29
31
  "build:compiler": "moon build --target js",
30
32
  "build:copy": "node scripts/build.js",
31
33
  "build": "npm run build:compiler && npm run build:copy",
34
+ "lint": "moon check",
35
+ "lint:fix": "moon fmt",
36
+ "format": "moon fmt && prettier --write ./bin ./lib ./scripts ./stdlib ./index.d.ts ./index.js ./index.mjs",
37
+ "format:check": "moon fmt --check && prettier --check ./bin ./lib ./scripts ./stdlib ./index.d.ts ./index.js ./index.mjs",
38
+ "typecheck": "moon check",
39
+ "check": "npm run lint && npm run format:check && npm run build && npm run typecheck",
32
40
  "sync": "node scripts/sync-version.js",
33
41
  "prepublishOnly": "npm run sync && npm run build"
34
42
  },
@@ -58,5 +66,8 @@
58
66
  "homepage": "https://purus.work",
59
67
  "engines": {
60
68
  "node": ">=18"
69
+ },
70
+ "devDependencies": {
71
+ "prettier": "^3.8.1"
61
72
  }
62
73
  }
@@ -0,0 +1,97 @@
1
+ // Purus stdlib: p-array — Array utility functions
2
+ //
3
+ // test: node -e "const a = require('./stdlib/p-array'); console.log(a.mod.range(1,5))"
4
+
5
+ exports.mod = {
6
+ isarray(val) {
7
+ return Array.isArray(val);
8
+ },
9
+ from(val) {
10
+ return Array.from(val);
11
+ },
12
+ of(...args) {
13
+ return Array.of(...args);
14
+ },
15
+ len(arr) {
16
+ return arr.length;
17
+ },
18
+ first(arr) {
19
+ return arr[0];
20
+ },
21
+ last(arr) {
22
+ return arr[arr.length - 1];
23
+ },
24
+ range(start, end, step) {
25
+ const s = step || 1;
26
+ const result = [];
27
+ for (let i = start; i < end; i += s) result.push(i);
28
+ return result;
29
+ },
30
+ flatten(arr, depth) {
31
+ return arr.flat(depth === undefined ? Infinity : depth);
32
+ },
33
+ unique(arr) {
34
+ return [...new Set(arr)];
35
+ },
36
+ zip(...arrs) {
37
+ const minLen = Math.min(...arrs.map((a) => a.length));
38
+ const result = [];
39
+ for (let i = 0; i < minLen; i++) {
40
+ result.push(arrs.map((a) => a[i]));
41
+ }
42
+ return result;
43
+ },
44
+ unzip(arr) {
45
+ if (arr.length === 0) return [];
46
+ const result = arr[0].map(() => []);
47
+ for (const tuple of arr) {
48
+ for (let i = 0; i < tuple.length; i++) {
49
+ result[i].push(tuple[i]);
50
+ }
51
+ }
52
+ return result;
53
+ },
54
+ chunk(arr, size) {
55
+ const result = [];
56
+ for (let i = 0; i < arr.length; i += size) {
57
+ result.push(arr.slice(i, i + size));
58
+ }
59
+ return result;
60
+ },
61
+ sum(arr) {
62
+ return arr.reduce((a, b) => a + b, 0);
63
+ },
64
+ product(arr) {
65
+ return arr.reduce((a, b) => a * b, 1);
66
+ },
67
+ min(arr) {
68
+ return Math.min(...arr);
69
+ },
70
+ max(arr) {
71
+ return Math.max(...arr);
72
+ },
73
+ sortasc(arr) {
74
+ return [...arr].sort((a, b) => a - b);
75
+ },
76
+ sortdesc(arr) {
77
+ return [...arr].sort((a, b) => b - a);
78
+ },
79
+ compact(arr) {
80
+ return arr.filter(Boolean);
81
+ },
82
+ count(arr, fn) {
83
+ return arr.filter(fn).length;
84
+ },
85
+ groupby(arr, fn) {
86
+ const result = {};
87
+ for (const item of arr) {
88
+ const key = fn(item);
89
+ if (!result[key]) result[key] = [];
90
+ result[key].push(item);
91
+ }
92
+ return result;
93
+ },
94
+ };
95
+
96
+ exports.spread = null;
97
+ exports.constants = {};
@@ -0,0 +1,200 @@
1
+ // Purus stdlib: datetime — date/time utility functions
2
+ //
3
+ // test: node -e "const d = require('./stdlib/datetime'); console.log(d.mod.now())"
4
+
5
+ exports.mod = {
6
+ // --- current time ---
7
+ now() {
8
+ return Date.now();
9
+ },
10
+ today() {
11
+ const d = new Date();
12
+ return new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime();
13
+ },
14
+ timestamp() {
15
+ return Math.floor(Date.now() / 1000);
16
+ },
17
+
18
+ // --- create ---
19
+ create(year, month, day, hour, minute, second, ms) {
20
+ return new Date(
21
+ year,
22
+ (month || 1) - 1,
23
+ day || 1,
24
+ hour || 0,
25
+ minute || 0,
26
+ second || 0,
27
+ ms || 0,
28
+ ).getTime();
29
+ },
30
+ utccreate(year, month, day, hour, minute, second, ms) {
31
+ return Date.UTC(
32
+ year,
33
+ (month || 1) - 1,
34
+ day || 1,
35
+ hour || 0,
36
+ minute || 0,
37
+ second || 0,
38
+ ms || 0,
39
+ );
40
+ },
41
+ fromiso(str) {
42
+ return new Date(str).getTime();
43
+ },
44
+
45
+ // --- extract components (local) ---
46
+ year(t) {
47
+ return new Date(t).getFullYear();
48
+ },
49
+ month(t) {
50
+ return new Date(t).getMonth() + 1;
51
+ },
52
+ day(t) {
53
+ return new Date(t).getDate();
54
+ },
55
+ weekday(t) {
56
+ return new Date(t).getDay();
57
+ },
58
+ hour(t) {
59
+ return new Date(t).getHours();
60
+ },
61
+ minute(t) {
62
+ return new Date(t).getMinutes();
63
+ },
64
+ second(t) {
65
+ return new Date(t).getSeconds();
66
+ },
67
+ ms(t) {
68
+ return new Date(t).getMilliseconds();
69
+ },
70
+
71
+ // --- extract components (UTC) ---
72
+ utcyear(t) {
73
+ return new Date(t).getUTCFullYear();
74
+ },
75
+ utcmonth(t) {
76
+ return new Date(t).getUTCMonth() + 1;
77
+ },
78
+ utcday(t) {
79
+ return new Date(t).getUTCDate();
80
+ },
81
+ utcweekday(t) {
82
+ return new Date(t).getUTCDay();
83
+ },
84
+ utchour(t) {
85
+ return new Date(t).getUTCHours();
86
+ },
87
+ utcminute(t) {
88
+ return new Date(t).getUTCMinutes();
89
+ },
90
+ utcsecond(t) {
91
+ return new Date(t).getUTCSeconds();
92
+ },
93
+ utcms(t) {
94
+ return new Date(t).getUTCMilliseconds();
95
+ },
96
+
97
+ // --- extract components (timezone-aware) ---
98
+ _tzpart(t, tz, type) {
99
+ const parts = new Intl.DateTimeFormat("en-US", {
100
+ timeZone: tz,
101
+ year: "numeric",
102
+ month: "numeric",
103
+ day: "numeric",
104
+ hour: "numeric",
105
+ minute: "numeric",
106
+ second: "numeric",
107
+ fractionalSecondDigits: 3,
108
+ hour12: false,
109
+ }).formatToParts(new Date(t));
110
+ const p = parts.find((p) => p.type === type);
111
+ return p ? parseInt(p.value, 10) : 0;
112
+ },
113
+ tzyear(t, tz) {
114
+ return this._tzpart(t, tz, "year");
115
+ },
116
+ tzmonth(t, tz) {
117
+ return this._tzpart(t, tz, "month");
118
+ },
119
+ tzday(t, tz) {
120
+ return this._tzpart(t, tz, "day");
121
+ },
122
+ tzweekday(t, tz) {
123
+ const d = new Intl.DateTimeFormat("en-US", {
124
+ timeZone: tz,
125
+ weekday: "short",
126
+ }).format(new Date(t));
127
+ return ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"].indexOf(d);
128
+ },
129
+ tzhour(t, tz) {
130
+ return this._tzpart(t, tz, "hour") % 24;
131
+ },
132
+ tzminute(t, tz) {
133
+ return this._tzpart(t, tz, "minute");
134
+ },
135
+ tzsecond(t, tz) {
136
+ return this._tzpart(t, tz, "second");
137
+ },
138
+
139
+ // --- format ---
140
+ toiso(t) {
141
+ return new Date(t).toISOString();
142
+ },
143
+ tolocale(t, locale, options) {
144
+ return new Date(t).toLocaleString(locale, options);
145
+ },
146
+ todate(t, locale, options) {
147
+ return new Date(t).toLocaleDateString(locale, options);
148
+ },
149
+ totime(t, locale, options) {
150
+ return new Date(t).toLocaleTimeString(locale, options);
151
+ },
152
+ format(t, tz, locale, options) {
153
+ return new Date(t).toLocaleString(locale || "en-US", {
154
+ timeZone: tz,
155
+ ...options,
156
+ });
157
+ },
158
+
159
+ // --- arithmetic ---
160
+ addms(t, n) {
161
+ return t + n;
162
+ },
163
+ addseconds(t, n) {
164
+ return t + n * 1000;
165
+ },
166
+ addminutes(t, n) {
167
+ return t + n * 60000;
168
+ },
169
+ addhours(t, n) {
170
+ return t + n * 3600000;
171
+ },
172
+ adddays(t, n) {
173
+ return t + n * 86400000;
174
+ },
175
+
176
+ // --- comparison ---
177
+ diff(a, b) {
178
+ return a - b;
179
+ },
180
+ diffdays(a, b) {
181
+ return (a - b) / 86400000;
182
+ },
183
+ diffhours(a, b) {
184
+ return (a - b) / 3600000;
185
+ },
186
+ diffminutes(a, b) {
187
+ return (a - b) / 60000;
188
+ },
189
+ diffseconds(a, b) {
190
+ return (a - b) / 1000;
191
+ },
192
+
193
+ // --- timezone info ---
194
+ offset(t) {
195
+ return new Date(t || Date.now()).getTimezoneOffset();
196
+ },
197
+ localtz() {
198
+ return Intl.DateTimeFormat().resolvedOptions().timeZone;
199
+ },
200
+ };
@@ -0,0 +1,45 @@
1
+ // Purus stdlib: p-error — Error creation and inspection utilities
2
+ //
3
+ // test: node -e "const e = require('./stdlib/p-error'); console.log(e.mod.create('oops').message)"
4
+
5
+ exports.mod = {
6
+ create(message) {
7
+ return new Error(message);
8
+ },
9
+ type(message) {
10
+ return new TypeError(message);
11
+ },
12
+ range(message) {
13
+ return new RangeError(message);
14
+ },
15
+ reference(message) {
16
+ return new ReferenceError(message);
17
+ },
18
+ syntax(message) {
19
+ return new SyntaxError(message);
20
+ },
21
+ uri(message) {
22
+ return new URIError(message);
23
+ },
24
+ iserror(val) {
25
+ return val instanceof Error;
26
+ },
27
+ message(err) {
28
+ return err instanceof Error ? err.message : String(err);
29
+ },
30
+ name(err) {
31
+ return err instanceof Error ? err.name : "Error";
32
+ },
33
+ stack(err) {
34
+ return err instanceof Error ? err.stack || "" : "";
35
+ },
36
+ cause(err) {
37
+ return err instanceof Error ? err.cause : undefined;
38
+ },
39
+ wrap(message, cause) {
40
+ return new Error(message, { cause });
41
+ },
42
+ };
43
+
44
+ exports.spread = null;
45
+ exports.constants = {};
@@ -0,0 +1,18 @@
1
+ // Purus stdlib: json — JSON parse / stringify utilities
2
+ //
3
+ // test: node -e "const j = require('./stdlib/json'); console.log(j.mod.parse('{\"a\":1}'))"
4
+
5
+ exports.mod = {
6
+ parse(str) {
7
+ return JSON.parse(str);
8
+ },
9
+ stringify(val) {
10
+ return JSON.stringify(val);
11
+ },
12
+ prettify(val, indent) {
13
+ return JSON.stringify(val, null, indent || 2);
14
+ },
15
+ };
16
+
17
+ exports.spread = "JSON";
18
+ exports.constants = {};
@@ -0,0 +1,57 @@
1
+ // Purus stdlib: p-map — Map creation and operations
2
+ //
3
+ // test: node -e "const m = require('./stdlib/p-map'); const x = m.mod.from([['a',1]]); console.log(m.mod.get(x,'a'))"
4
+
5
+ exports.mod = {
6
+ create(...pairs) {
7
+ return new Map(pairs);
8
+ },
9
+ from(iterable) {
10
+ return new Map(iterable);
11
+ },
12
+ fromobject(obj) {
13
+ return new Map(Object.entries(obj));
14
+ },
15
+ get(map, key) {
16
+ return map.get(key);
17
+ },
18
+ set(map, key, value) {
19
+ const m = new Map(map);
20
+ m.set(key, value);
21
+ return m;
22
+ },
23
+ delete(map, key) {
24
+ const m = new Map(map);
25
+ m.delete(key);
26
+ return m;
27
+ },
28
+ has(map, key) {
29
+ return map.has(key);
30
+ },
31
+ size(map) {
32
+ return map.size;
33
+ },
34
+ keys(map) {
35
+ return [...map.keys()];
36
+ },
37
+ values(map) {
38
+ return [...map.values()];
39
+ },
40
+ entries(map) {
41
+ return [...map.entries()];
42
+ },
43
+ clear(map) {
44
+ const m = new Map(map);
45
+ m.clear();
46
+ return m;
47
+ },
48
+ toobject(map) {
49
+ return Object.fromEntries(map);
50
+ },
51
+ merge(a, b) {
52
+ return new Map([...a, ...b]);
53
+ },
54
+ };
55
+
56
+ exports.spread = null;
57
+ exports.constants = {};