unrun 0.2.9 → 0.2.11

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/dist/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { n as unrunCli, r as unrunSync, t as unrun } from "./src-D87jO6Ui.mjs";
1
+ import { n as unrunCli, r as unrunSync, t as unrun } from "./src-DyfW0b4_.mjs";
2
2
 
3
3
  export { unrun, unrunCli, unrunSync };
@@ -111,99 +111,163 @@ function isPathWithinDirectory(parent, child) {
111
111
  * nested node_modules so they keep working once executed from .unrun.
112
112
  */
113
113
  function createExternalResolver(options) {
114
- const projectNodeModules = path.resolve(process.cwd(), "node_modules");
114
+ const entryDir = path.dirname(options.path);
115
+ const entryRequire = createRequire(options.path);
116
+ const canResolveFromEntry = (specifier) => {
117
+ try {
118
+ entryRequire.resolve(specifier);
119
+ return true;
120
+ } catch {
121
+ return false;
122
+ }
123
+ };
115
124
  return function external(id, importer) {
116
125
  if (!id || id.startsWith("\0")) return false;
117
126
  if (id.startsWith(".") || id.startsWith("#") || path.isAbsolute(id)) return false;
118
127
  if (isBuiltinModuleSpecifier(id)) return true;
119
128
  const importerPath = normalizeImporterPath(importer, options.path);
120
129
  try {
121
- if (!isPathWithinDirectory(projectNodeModules, createRequire(importerPath).resolve(id))) return false;
130
+ const containingNodeModules = findContainingNodeModules(createRequire(importerPath).resolve(id));
131
+ if (!containingNodeModules) return false;
132
+ const ownerDir = path.dirname(containingNodeModules);
133
+ const ownerInsideEntry = isPathWithinDirectory(entryDir, ownerDir);
134
+ const entryInsideOwner = isPathWithinDirectory(ownerDir, entryDir);
135
+ if (ownerInsideEntry && !entryInsideOwner) return false;
136
+ if (!canResolveFromEntry(id)) return false;
122
137
  } catch {}
123
138
  return true;
124
139
  };
125
140
  }
141
+ function findContainingNodeModules(filePath) {
142
+ let current = path.dirname(filePath);
143
+ const { root } = path.parse(current);
144
+ while (true) {
145
+ if (path.basename(current) === "node_modules") return current;
146
+ if (current === root) break;
147
+ current = path.dirname(current);
148
+ }
149
+ }
126
150
 
127
151
  //#endregion
128
152
  //#region src/plugins/console-output-customizer.ts
129
- /**
130
- * Attach a util.inspect customizer to namespace-like module objects produced by rolldown helpers
131
- * so console.log prints concrete values instead of [Getter], while preserving live bindings.
132
- *
133
- * Cleaner strategy: inject a tiny helper at the top of the chunk and minimally augment
134
- * rolldown helpers (__export and __copyProps) right inside their definitions, before use.
135
- */
153
+ const INSPECT_HELPER_SNIPPET = `(function(){
154
+ function __unrun__fmt(names, getter, np){
155
+ var onlyDefault = names.length === 1 && names[0] === "default";
156
+ var o = np ? Object.create(null) : {};
157
+ for (var i = 0; i < names.length; i++) {
158
+ var n = names[i];
159
+ try { o[n] = getter(n) } catch {}
160
+ }
161
+ if (onlyDefault) {
162
+ try {
163
+ var s = JSON.stringify(o.default);
164
+ if (s !== undefined) {
165
+ s = s.replace(/"([^"]+)":/g, "$1: ").replace(/,/g, ", ").replace(/{/g, "{ ").replace(/}/g, " }");
166
+ return "[Module: null prototype] { default: " + s + " }";
167
+ }
168
+ } catch {}
169
+ return "[Module: null prototype] { default: " + String(o.default) + " }";
170
+ }
171
+ return o;
172
+ }
173
+ function __unrun__setInspect(obj, names, getter, np){
174
+ try {
175
+ var __insp = Symbol.for('nodejs.util.inspect.custom');
176
+ Object.defineProperty(obj, __insp, {
177
+ value: function(){ return __unrun__fmt(names, getter, np) },
178
+ enumerable: false, configurable: true
179
+ });
180
+ } catch {}
181
+ return obj;
182
+ }
183
+ try {
184
+ Object.defineProperty(globalThis, "__unrun__setInspect", {
185
+ value: __unrun__setInspect,
186
+ enumerable: false,
187
+ });
188
+ } catch {}
189
+ })();`;
190
+ const WRAPPER_SNIPPET = `(function __unrun__wrapRolldownHelpers(){
191
+ if (typeof __unrun__setInspect !== "function") return;
192
+ if (typeof __export === "function" && !__export.__unrunPatched) {
193
+ var __unrun__origExport = __export;
194
+ var __unrun__patchedExport = (...__unrun__args) => {
195
+ var __unrun__target = __unrun__origExport(...__unrun__args);
196
+ if (__unrun__target && typeof __unrun__target === "object") {
197
+ try {
198
+ var __unrun__map = (__unrun__args[0] && typeof __unrun__args[0] === "object") ? __unrun__args[0] : {};
199
+ var __unrun__names = Object.keys(__unrun__map).filter(function(n){ return n !== "__esModule" });
200
+ __unrun__setInspect(
201
+ __unrun__target,
202
+ __unrun__names,
203
+ function(n){
204
+ var getter = __unrun__map[n];
205
+ return typeof getter === "function" ? getter() : getter;
206
+ },
207
+ false,
208
+ );
209
+ } catch {}
210
+ }
211
+ return __unrun__target;
212
+ };
213
+ __unrun__patchedExport.__unrunPatched = true;
214
+ __export = __unrun__patchedExport;
215
+ }
216
+ if (typeof __copyProps === "function" && !__copyProps.__unrunPatched) {
217
+ var __unrun__origCopyProps = __copyProps;
218
+ var __unrun__patchedCopyProps = (...__unrun__args) => {
219
+ var __unrun__result = __unrun__origCopyProps(...__unrun__args);
220
+ if (__unrun__result && typeof __unrun__result === "object") {
221
+ try {
222
+ var __unrun__names = Object.keys(__unrun__result).filter(function(n){ return n !== "__esModule" });
223
+ __unrun__setInspect(__unrun__result, __unrun__names, function(n){ return __unrun__result[n] }, true);
224
+ } catch {}
225
+ }
226
+ return __unrun__result;
227
+ };
228
+ __unrun__patchedCopyProps.__unrunPatched = true;
229
+ __copyProps = __unrun__patchedCopyProps;
230
+ }
231
+ })();`;
232
+ const HELPER_DECLARATION_PATTERN = /__unrun__setInspect\b/;
233
+ const WRAPPER_MARKER = "__unrun__wrapRolldownHelpers";
136
234
  function createConsoleOutputCustomizer() {
137
235
  return {
138
236
  name: "unrun-console-output-customizer",
139
237
  generateBundle: { handler(_, bundle$1) {
140
238
  for (const chunk of Object.values(bundle$1)) {
141
239
  if (chunk.type !== "chunk") continue;
142
- if (!/__unrun__setInspect\b/.test(chunk.code)) {
143
- const helper = [
144
- "(function(){",
145
- " function __unrun__fmt(names, getter, np){",
146
- " var onlyDefault = names.length === 1 && names[0] === \"default\";",
147
- " var o = np ? Object.create(null) : {};",
148
- " for (var i = 0; i < names.length; i++) {",
149
- " var n = names[i];",
150
- " try { o[n] = getter(n) } catch {}",
151
- " }",
152
- " if (onlyDefault) {",
153
- " try {",
154
- " var s = JSON.stringify(o.default);",
155
- " if (s !== undefined) {",
156
- " s = s.replace(/\"([^\"]+)\":/g, \"$1: \").replace(/,/g, \", \").replace(/{/g, \"{ \").replace(/}/g, \" }\");",
157
- " return \"[Module: null prototype] { default: \" + s + \" }\";",
158
- " }",
159
- " } catch {}",
160
- " return \"[Module: null prototype] { default: \" + String(o.default) + \" }\";",
161
- " }",
162
- " return o;",
163
- " }",
164
- " function __unrun__setInspect(obj, names, getter, np){",
165
- " try {",
166
- " var __insp = Symbol.for('nodejs.util.inspect.custom')",
167
- " Object.defineProperty(obj, __insp, {",
168
- " value: function(){ return __unrun__fmt(names, getter, np) },",
169
- " enumerable: false, configurable: true",
170
- " })",
171
- " } catch {}",
172
- " return obj;",
173
- " }",
174
- " try { Object.defineProperty(globalThis, \"__unrun__setInspect\", { value: __unrun__setInspect, enumerable: false }) } catch {}",
175
- "})();"
176
- ].join("\n");
177
- if (chunk.code.startsWith("#!")) {
178
- const nl = chunk.code.indexOf("\n");
179
- if (nl !== -1) chunk.code = `${chunk.code.slice(0, nl + 1)}${helper}\n${chunk.code.slice(nl + 1)}`;
180
- else chunk.code = `${helper}\n${chunk.code}`;
181
- } else chunk.code = `${helper}\n${chunk.code}`;
182
- }
183
- chunk.code = chunk.code.replace(/var\s+__export\s*=\s*\(all\)\s*=>\s*\{([\s\S]*?)return\s+target;\s*\}/, (_m, body) => {
184
- return `var __export = (all) => {\n${[
185
- body,
186
- " try {",
187
- " var __names = Object.keys(all).filter(function(n){ return n !== \"__esModule\" })",
188
- " __unrun__setInspect(target, __names, function(n){ return all[n]() }, false)",
189
- " } catch {}",
190
- " return target;"
191
- ].join("\n")}\n}`;
192
- });
193
- chunk.code = chunk.code.replace(/var\s+__copyProps\s*=\s*\(to,\s*from,\s*except,\s*desc\)\s*=>\s*\{([\s\S]*?)return\s+to;\s*\};/, (_m, body) => {
194
- return `var __copyProps = (to, from, except, desc) => {\n${[
195
- body,
196
- " try {",
197
- " var __names = Object.keys(to).filter(function(n){ return n !== \"__esModule\" })",
198
- " __unrun__setInspect(to, __names, function(n){ return to[n] }, true)",
199
- " } catch {}",
200
- " return to;"
201
- ].join("\n")}\n};`;
202
- });
240
+ injectInspectHelper(chunk);
241
+ injectHelperWrappers(chunk);
203
242
  }
204
243
  } }
205
244
  };
206
245
  }
246
+ function injectInspectHelper(chunk) {
247
+ if (HELPER_DECLARATION_PATTERN.test(chunk.code)) return;
248
+ chunk.code = chunk.code.startsWith("#!") ? insertAfterShebang(chunk.code, `${INSPECT_HELPER_SNIPPET}\n`) : `${INSPECT_HELPER_SNIPPET}\n${chunk.code}`;
249
+ }
250
+ function injectHelperWrappers(chunk) {
251
+ if (chunk.code.includes(WRAPPER_MARKER)) return;
252
+ const insertIndex = findRuntimeBoundary(chunk.code);
253
+ const snippet = `${WRAPPER_SNIPPET}\n`;
254
+ if (insertIndex === -1) {
255
+ chunk.code = `${chunk.code}\n${snippet}`;
256
+ return;
257
+ }
258
+ chunk.code = `${chunk.code.slice(0, insertIndex)}${snippet}${chunk.code.slice(insertIndex)}`;
259
+ }
260
+ function findRuntimeBoundary(code) {
261
+ const markerIndex = code.indexOf("//#endregion");
262
+ if (markerIndex === -1) return -1;
263
+ const newlineIndex = code.indexOf("\n", markerIndex);
264
+ return newlineIndex === -1 ? code.length : newlineIndex + 1;
265
+ }
266
+ function insertAfterShebang(code, insertion) {
267
+ const nl = code.indexOf("\n");
268
+ if (nl === -1) return `${code}\n${insertion}`;
269
+ return `${code.slice(0, nl + 1)}${insertion}${code.slice(nl + 1)}`;
270
+ }
207
271
 
208
272
  //#endregion
209
273
  //#region src/plugins/json-loader.ts
@@ -382,6 +446,7 @@ function createSourceContextShimsPlugin() {
382
446
  return null;
383
447
  }
384
448
  let __MODIFIED_CODE__ = false;
449
+ if (id.replaceAll("\\", "/").includes("/node_modules/")) return null;
385
450
  if (code.includes("import.meta.resolve")) {
386
451
  const replaced = code.replaceAll(/import\.meta\.resolve!?\s*\(\s*(["'])([^"']+)\1\s*\)/g, (_m, _q, spec) => {
387
452
  const url = pathToFileURL(path.resolve(path.dirname(id), spec)).href;
@@ -392,21 +457,36 @@ function createSourceContextShimsPlugin() {
392
457
  __MODIFIED_CODE__ = true;
393
458
  }
394
459
  }
395
- if (/__filename|__dirname|import\s*\.\s*meta\s*\.\s*url/.test(code)) {
460
+ const usesFilename = /\b__filename\b/.test(code);
461
+ const declaresFilename = /\b(?:const|let|var)\s+__filename\b/.test(code);
462
+ const usesDirname = /\b__dirname\b/.test(code);
463
+ const declaresDirname = /\b(?:const|let|var)\s+__dirname\b/.test(code);
464
+ const hasImportMetaUrl = /\bimport\s*\.\s*meta\s*\.\s*url\b/.test(code);
465
+ const needsFilenameShim = usesFilename && !declaresFilename;
466
+ const needsDirnameShim = usesDirname && !declaresDirname;
467
+ if (needsFilenameShim || needsDirnameShim || hasImportMetaUrl) {
396
468
  const file = id;
397
469
  const dir = path.dirname(id);
398
470
  const url = pathToFileURL(id).href;
399
- const prologue = `const __filename = ${JSON.stringify(file)}\nconst __dirname = ${JSON.stringify(dir)}\n`;
400
- const protectedStrings = [];
401
- let protectedCode = code.replaceAll(/(["'])[^"']*import\s*\.\s*meta\s*\.\s*url[^"']*\1\s*:/g, (match) => {
402
- const placeholder = `__PROTECTED_STRING_${protectedStrings.length}__`;
403
- protectedStrings.push(match);
404
- return placeholder;
405
- });
406
- protectedCode = protectedCode.replaceAll(/\bimport\s*\.\s*meta\s*\.\s*url\b/g, JSON.stringify(url));
407
- for (const [i, protectedString] of protectedStrings.entries()) protectedCode = protectedCode.replace(`__PROTECTED_STRING_${i}__`, protectedString);
408
- code = prologue + protectedCode;
409
- __MODIFIED_CODE__ = true;
471
+ const prologueLines = [];
472
+ if (needsFilenameShim) prologueLines.push(`const __filename = ${JSON.stringify(file)}`);
473
+ if (needsDirnameShim) prologueLines.push(`const __dirname = ${JSON.stringify(dir)}`);
474
+ let transformedCode = code;
475
+ if (hasImportMetaUrl) {
476
+ const protectedStrings = [];
477
+ transformedCode = transformedCode.replaceAll(/(["'])[^"']*import\s*\.\s*meta\s*\.\s*url[^"']*\1\s*:/g, (match) => {
478
+ const placeholder = `__PROTECTED_STRING_${protectedStrings.length}__`;
479
+ protectedStrings.push(match);
480
+ return placeholder;
481
+ });
482
+ transformedCode = transformedCode.replaceAll(/\bimport\s*\.\s*meta\s*\.\s*url\b/g, JSON.stringify(url));
483
+ for (const [i, protectedString] of protectedStrings.entries()) transformedCode = transformedCode.replace(`__PROTECTED_STRING_${i}__`, protectedString);
484
+ }
485
+ if (prologueLines.length > 0) transformedCode = `${prologueLines.join("\n")}\n${transformedCode}`;
486
+ if (transformedCode !== code) {
487
+ code = transformedCode;
488
+ __MODIFIED_CODE__ = true;
489
+ }
410
490
  }
411
491
  return __MODIFIED_CODE__ ? { code } : null;
412
492
  }
@@ -1,4 +1,4 @@
1
- import { t as unrun } from "../src-D87jO6Ui.mjs";
1
+ import { t as unrun } from "../src-DyfW0b4_.mjs";
2
2
  import { runAsWorker } from "synckit";
3
3
 
4
4
  //#region src/sync/worker.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unrun",
3
- "version": "0.2.9",
3
+ "version": "0.2.11",
4
4
  "description": "A tool to load and execute any JavaScript or TypeScript code at runtime.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -39,12 +39,12 @@
39
39
  }
40
40
  },
41
41
  "dependencies": {
42
- "@oxc-project/runtime": "^0.97.0",
43
- "rolldown": "1.0.0-beta.50"
42
+ "@oxc-project/runtime": "^0.96.0",
43
+ "rolldown": "1.0.0-beta.51"
44
44
  },
45
45
  "devDependencies": {
46
- "@sxzz/eslint-config": "^7.2.10",
47
- "@sxzz/prettier-config": "^2.2.4",
46
+ "@sxzz/eslint-config": "^7.3.0",
47
+ "@sxzz/prettier-config": "^2.2.5",
48
48
  "@types/node": "^24.10.1",
49
49
  "acorn": "^8.15.0",
50
50
  "bumpp": "^10.3.1",
@@ -53,7 +53,7 @@
53
53
  "consola": "^3.4.2",
54
54
  "defu": "^6.1.4",
55
55
  "destr": "^2.0.5",
56
- "esbuild": "^0.27.0",
56
+ "esbuild": "^0.25.12",
57
57
  "eslint": "^9.39.1",
58
58
  "estree-walker": "^3.0.3",
59
59
  "etag": "^1.8.1",
@@ -71,19 +71,22 @@
71
71
  "react-dom": "^19.2.0",
72
72
  "reflect-metadata": "^0.2.2",
73
73
  "synckit": "^0.11.11",
74
+ "test-ecosystem-ci": "^0.0.1",
74
75
  "tinyexec": "^1.0.2",
75
- "tsdown": "^0.16.3",
76
+ "tsdown": "^0.16.5",
76
77
  "tsx": "^4.20.6",
77
78
  "typedoc": "^0.28.14",
78
79
  "typedoc-plugin-markdown": "^4.9.0",
79
80
  "typedoc-vitepress-theme": "^1.1.2",
80
81
  "typescript": "^5.9.3",
81
82
  "unconfig": "^7.4.1",
83
+ "unplugin-vue": "^7.0.8",
82
84
  "vite": "^7.2.2",
83
85
  "vitepress": "2.0.0-alpha.12",
84
86
  "vitepress-plugin-group-icons": "^1.6.5",
85
87
  "vitest": "4.0.8",
86
88
  "vue": "^3.5.24",
89
+ "vue-tsc": "^3.1.4",
87
90
  "zod": "^4.1.12"
88
91
  },
89
92
  "engines": {
@@ -95,8 +98,14 @@
95
98
  "lint:fix": "pnpm run lint --fix",
96
99
  "build": "tsdown",
97
100
  "dev": "tsdown --watch",
101
+ "pretest": "node ./scripts/manage-pnpm-override.mjs add",
98
102
  "test": "vitest",
103
+ "posttest": "node ./scripts/manage-pnpm-override.mjs remove",
104
+ "pretest:run": "node ./scripts/manage-pnpm-override.mjs add",
99
105
  "test:run": "vitest run",
106
+ "posttest:run": "node ./scripts/manage-pnpm-override.mjs remove",
107
+ "ecosystem-ci": "ecosystem-ci",
108
+ "ecosystem-ci:force": "ecosystem-ci --force",
100
109
  "test:update-fixtures": "node ./dist/cli.mjs ./scripts/update-fixtures.ts",
101
110
  "benchmark": "tsdown -c benchmark/tsdown.config.ts && node ./benchmark/dist/benchmark.mjs",
102
111
  "typecheck": "tsc --noEmit",