almostnode 0.2.3 → 0.2.5

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/runtime.d.ts CHANGED
@@ -36,6 +36,8 @@ export declare class Runtime {
36
36
  private process;
37
37
  private moduleCache;
38
38
  private options;
39
+ /** Cache for pre-processed code (after ESM transform) before eval */
40
+ private processedCodeCache;
39
41
  constructor(vfs: VirtualFS, options?: RuntimeOptions);
40
42
  /**
41
43
  * Set up a polyfilled TextDecoder that handles binary encodings
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,KAAK,EAAY,cAAc,EAAmB,MAAM,qBAAqB,CAAC;AAGrF,OAAO,EAAiB,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAqLzD,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;CACvD;AAED,MAAM,WAAW,eAAe;IAC9B,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IACtB,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AA+iBD;;;;GAIG;AACH,qBAAa,OAAO;IAClB,OAAO,CAAC,GAAG,CAAY;IACvB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,WAAW,CAA8B;IACjD,OAAO,CAAC,OAAO,CAAiB;gBAEpB,GAAG,EAAE,SAAS,EAAE,OAAO,GAAE,cAAmB;IA0BxD;;OAEG;IACH,OAAO,CAAC,wBAAwB;IA+EhC;;OAEG;IACH,OAAO,CACL,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,MAAoB,GAC7B;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;IA4EvC;;;OAGG;IACH,WAAW,SAlFH,MAAM,aACF,MAAM,KACf;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAgFZ;IAE3B;;OAEG;IACG,YAAY,CAChB,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,MAAoB,GAC7B,OAAO,CAAC,cAAc,CAAC;IAI1B;;OAEG;IACH,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;IAK/D;;OAEG;IACH,WAAW,aARO,MAAM,KAAG;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAQpC;IAE3B;;OAEG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAI7D;;OAEG;IACH,UAAU,IAAI,IAAI;IAIlB;;OAEG;IACH,MAAM,IAAI,SAAS;IAInB;;OAEG;IACH,UAAU,IAAI,OAAO;CAGtB;AAED;;GAEG;AACH,wBAAgB,OAAO,CACrB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,SAAS,EACd,OAAO,CAAC,EAAE,cAAc,GACvB;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAGtC;AAGD,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAErF,eAAe,OAAO,CAAC"}
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,KAAK,EAAY,cAAc,EAAmB,MAAM,qBAAqB,CAAC;AAKrF,OAAO,EAAiB,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAqLzD,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;CACvD;AAED,MAAM,WAAW,eAAe;IAC9B,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IACtB,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAqmBD;;;;GAIG;AACH,qBAAa,OAAO;IAClB,OAAO,CAAC,GAAG,CAAY;IACvB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,WAAW,CAA8B;IACjD,OAAO,CAAC,OAAO,CAAiB;IAChC,qEAAqE;IACrE,OAAO,CAAC,kBAAkB,CAAkC;gBAEhD,GAAG,EAAE,SAAS,EAAE,OAAO,GAAE,cAAmB;IA0BxD;;OAEG;IACH,OAAO,CAAC,wBAAwB;IA+EhC;;OAEG;IACH,OAAO,CACL,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,MAAoB,GAC7B;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;IA6EvC;;;OAGG;IACH,WAAW,SAnFH,MAAM,aACF,MAAM,KACf;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAiFZ;IAE3B;;OAEG;IACG,YAAY,CAChB,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,MAAoB,GAC7B,OAAO,CAAC,cAAc,CAAC;IAI1B;;OAEG;IACH,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;IAK/D;;OAEG;IACH,WAAW,aARO,MAAM,KAAG;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAQpC;IAE3B;;OAEG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAI7D;;OAEG;IACH,UAAU,IAAI,IAAI;IAIlB;;OAEG;IACH,MAAM,IAAI,SAAS;IAInB;;OAEG;IACH,UAAU,IAAI,OAAO;CAGtB;AAED;;GAEG;AACH,wBAAgB,OAAO,CACrB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,SAAS,EACd,OAAO,CAAC,EAAE,cAAc,GACvB;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAGtC;AAGD,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAErF,eAAe,OAAO,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Type definition for package.json files
3
+ */
4
+ export interface PackageJson {
5
+ name?: string;
6
+ version?: string;
7
+ main?: string;
8
+ module?: string;
9
+ types?: string;
10
+ exports?: Record<string, unknown> | string;
11
+ dependencies?: Record<string, string>;
12
+ devDependencies?: Record<string, string>;
13
+ peerDependencies?: Record<string, string>;
14
+ [key: string]: unknown;
15
+ }
16
+ //# sourceMappingURL=package-json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-json.d.ts","sourceRoot":"","sources":["../../src/types/package-json.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Simple hash function for content-based cache invalidation.
3
+ * Uses djb2-style hashing for fast string hashing.
4
+ */
5
+ export declare function simpleHash(str: string): string;
6
+ //# sourceMappingURL=hash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/utils/hash.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAO9C"}
@@ -6,6 +6,7 @@ export interface FSNode {
6
6
  type: 'file' | 'directory';
7
7
  content?: Uint8Array;
8
8
  children?: Map<string, FSNode>;
9
+ mtime: number;
9
10
  }
10
11
  type VFSChangeListener = (path: string, content: string) => void;
11
12
  type VFSDeleteListener = (path: string) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"virtual-fs.d.ts","sourceRoot":"","sources":["../src/virtual-fs.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"virtual-fs.d.ts","sourceRoot":"","sources":["../src/virtual-fs.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "almostnode",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "description": "Node.js in your browser. Just like that.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -6,6 +6,7 @@
6
6
  import { DevServer, DevServerOptions, ResponseData, HMRUpdate } from '../dev-server';
7
7
  import { VirtualFS } from '../virtual-fs';
8
8
  import { Buffer } from '../shims/stream';
9
+ import { simpleHash } from '../utils/hash';
9
10
 
10
11
  // Check if we're in a real browser environment (not jsdom or Node.js)
11
12
  const isBrowser = typeof window !== 'undefined' &&
@@ -714,6 +715,9 @@ export class NextDevServer extends DevServer {
714
715
  /** Store options for later access (e.g., env vars) */
715
716
  private options: NextDevServerOptions;
716
717
 
718
+ /** Transform result cache for performance */
719
+ private transformCache: Map<string, { code: string; hash: string }> = new Map();
720
+
717
721
  constructor(vfs: VirtualFS, options: NextDevServerOptions) {
718
722
  super(vfs, options);
719
723
  this.options = options;
@@ -816,11 +820,16 @@ export class NextDevServer extends DevServer {
816
820
  return this.serveNextShim(pathname);
817
821
  }
818
822
 
819
- // Serve page components for client-side navigation
823
+ // Serve page components for client-side navigation (Pages Router)
820
824
  if (pathname.startsWith('/_next/pages/')) {
821
825
  return this.servePageComponent(pathname);
822
826
  }
823
827
 
828
+ // Serve app components for client-side navigation (App Router)
829
+ if (pathname.startsWith('/_next/app/')) {
830
+ return this.serveAppComponent(pathname);
831
+ }
832
+
824
833
  // Static assets from /_next/static/*
825
834
  if (pathname.startsWith('/_next/static/')) {
826
835
  return this.serveStaticAsset(pathname);
@@ -922,6 +931,28 @@ export class NextDevServer extends DevServer {
922
931
  return this.transformAndServe(pageFile, pageFile);
923
932
  }
924
933
 
934
+ /**
935
+ * Serve app components for client-side navigation (App Router)
936
+ * Maps /_next/app/app/about/page.js → /app/about/page.tsx (transformed)
937
+ */
938
+ private async serveAppComponent(pathname: string): Promise<ResponseData> {
939
+ // Extract the file path from /_next/app/app/about/page.js → /app/about/page
940
+ const filePath = pathname
941
+ .replace('/_next/app', '')
942
+ .replace(/\.js$/, '');
943
+
944
+ // Try different extensions
945
+ const extensions = ['.tsx', '.jsx', '.ts', '.js'];
946
+ for (const ext of extensions) {
947
+ const fullPath = filePath + ext;
948
+ if (this.exists(fullPath)) {
949
+ return this.transformAndServe(fullPath, fullPath);
950
+ }
951
+ }
952
+
953
+ return this.notFound(pathname);
954
+ }
955
+
925
956
  /**
926
957
  * Handle API route requests
927
958
  */
@@ -1672,17 +1703,117 @@ export class NextDevServer extends DevServer {
1672
1703
  <script type="module">
1673
1704
  import React from 'react';
1674
1705
  import ReactDOM from 'react-dom/client';
1675
- import Page from '${pageModulePath}';
1676
- ${layoutImports}
1677
1706
 
1678
- function App() {
1679
- return ${nestedJsx};
1707
+ const virtualBase = '${virtualPrefix}';
1708
+
1709
+ // Convert URL path to app router page module path
1710
+ function getAppPageModulePath(pathname) {
1711
+ let route = pathname;
1712
+ if (route.startsWith(virtualBase)) {
1713
+ route = route.slice(virtualBase.length);
1714
+ }
1715
+ route = route.replace(/^\\/+/, '/') || '/';
1716
+ // App Router: / -> /app/page, /about -> /app/about/page
1717
+ const pagePath = route === '/' ? '/app/page' : '/app' + route + '/page';
1718
+ return virtualBase + '/_next/app' + pagePath + '.js';
1719
+ }
1720
+
1721
+ // Get layout paths for a route
1722
+ function getLayoutPaths(pathname) {
1723
+ let route = pathname;
1724
+ if (route.startsWith(virtualBase)) {
1725
+ route = route.slice(virtualBase.length);
1726
+ }
1727
+ route = route.replace(/^\\/+/, '/') || '/';
1728
+
1729
+ // Build layout paths from root to current route
1730
+ const layouts = [virtualBase + '/_next/app/app/layout.js'];
1731
+ if (route !== '/') {
1732
+ const segments = route.split('/').filter(Boolean);
1733
+ let currentPath = '/app';
1734
+ for (const segment of segments) {
1735
+ currentPath += '/' + segment;
1736
+ layouts.push(virtualBase + '/_next/app' + currentPath + '/layout.js');
1737
+ }
1738
+ }
1739
+ return layouts;
1680
1740
  }
1681
1741
 
1742
+ // Dynamic page loader
1743
+ async function loadPage(pathname) {
1744
+ const modulePath = getAppPageModulePath(pathname);
1745
+ try {
1746
+ const module = await import(/* @vite-ignore */ modulePath);
1747
+ return module.default;
1748
+ } catch (e) {
1749
+ console.error('[Navigation] Failed to load page:', modulePath, e);
1750
+ return null;
1751
+ }
1752
+ }
1753
+
1754
+ // Load layouts (with caching)
1755
+ const layoutCache = new Map();
1756
+ async function loadLayouts(pathname) {
1757
+ const layoutPaths = getLayoutPaths(pathname);
1758
+ const layouts = [];
1759
+ for (const path of layoutPaths) {
1760
+ if (layoutCache.has(path)) {
1761
+ layouts.push(layoutCache.get(path));
1762
+ } else {
1763
+ try {
1764
+ const module = await import(/* @vite-ignore */ path);
1765
+ layoutCache.set(path, module.default);
1766
+ layouts.push(module.default);
1767
+ } catch (e) {
1768
+ // Layout might not exist for this segment, skip
1769
+ }
1770
+ }
1771
+ }
1772
+ return layouts;
1773
+ }
1774
+
1775
+ // Router component
1776
+ function Router() {
1777
+ const [Page, setPage] = React.useState(null);
1778
+ const [layouts, setLayouts] = React.useState([]);
1779
+ const [path, setPath] = React.useState(window.location.pathname);
1780
+
1781
+ React.useEffect(() => {
1782
+ Promise.all([loadPage(path), loadLayouts(path)]).then(([P, L]) => {
1783
+ if (P) setPage(() => P);
1784
+ setLayouts(L);
1785
+ });
1786
+ }, []);
1787
+
1788
+ React.useEffect(() => {
1789
+ const handleNavigation = async () => {
1790
+ const newPath = window.location.pathname;
1791
+ if (newPath !== path) {
1792
+ setPath(newPath);
1793
+ const [P, L] = await Promise.all([loadPage(newPath), loadLayouts(newPath)]);
1794
+ if (P) setPage(() => P);
1795
+ setLayouts(L);
1796
+ }
1797
+ };
1798
+ window.addEventListener('popstate', handleNavigation);
1799
+ return () => window.removeEventListener('popstate', handleNavigation);
1800
+ }, [path]);
1801
+
1802
+ if (!Page) return null;
1803
+
1804
+ // Build nested layout structure
1805
+ let content = React.createElement(Page);
1806
+ for (let i = layouts.length - 1; i >= 0; i--) {
1807
+ content = React.createElement(layouts[i], null, content);
1808
+ }
1809
+ return content;
1810
+ }
1811
+
1812
+ // Mark that we've initialized (for testing no-reload)
1813
+ window.__NEXT_INITIALIZED__ = Date.now();
1814
+
1682
1815
  ReactDOM.createRoot(document.getElementById('__next')).render(
1683
- React.createElement(React.StrictMode, null,
1684
- React.createElement(App)
1685
- )
1816
+ React.createElement(React.StrictMode, null, React.createElement(Router))
1686
1817
  );
1687
1818
  </script>
1688
1819
  </body>
@@ -1988,8 +2119,31 @@ export class NextDevServer extends DevServer {
1988
2119
  private async transformAndServe(filePath: string, urlPath: string): Promise<ResponseData> {
1989
2120
  try {
1990
2121
  const content = this.vfs.readFileSync(filePath, 'utf8');
2122
+ const hash = simpleHash(content);
2123
+
2124
+ // Check transform cache
2125
+ const cached = this.transformCache.get(filePath);
2126
+ if (cached && cached.hash === hash) {
2127
+ const buffer = Buffer.from(cached.code);
2128
+ return {
2129
+ statusCode: 200,
2130
+ statusMessage: 'OK',
2131
+ headers: {
2132
+ 'Content-Type': 'application/javascript; charset=utf-8',
2133
+ 'Content-Length': String(buffer.length),
2134
+ 'Cache-Control': 'no-cache',
2135
+ 'X-Transformed': 'true',
2136
+ 'X-Cache': 'hit',
2137
+ },
2138
+ body: buffer,
2139
+ };
2140
+ }
2141
+
1991
2142
  const transformed = await this.transformCode(content, urlPath);
1992
2143
 
2144
+ // Cache the transform result
2145
+ this.transformCache.set(filePath, { code: transformed, hash });
2146
+
1993
2147
  const buffer = Buffer.from(transformed);
1994
2148
  return {
1995
2149
  statusCode: 200,
@@ -6,6 +6,7 @@
6
6
  import { DevServer, DevServerOptions, ResponseData, HMRUpdate } from '../dev-server';
7
7
  import { VirtualFS } from '../virtual-fs';
8
8
  import { Buffer } from '../shims/stream';
9
+ import { simpleHash } from '../utils/hash';
9
10
 
10
11
  // Check if we're in a real browser environment (not jsdom or Node.js)
11
12
  // jsdom has window but doesn't have ServiceWorker or SharedArrayBuffer
@@ -279,6 +280,7 @@ export class ViteDevServer extends DevServer {
279
280
  private watcherCleanup: (() => void) | null = null;
280
281
  private options: ViteDevServerOptions;
281
282
  private hmrTargetWindow: Window | null = null;
283
+ private transformCache: Map<string, { code: string; hash: string }> = new Map();
282
284
 
283
285
  constructor(vfs: VirtualFS, options: ViteDevServerOptions) {
284
286
  super(vfs, options);
@@ -478,8 +480,31 @@ export class ViteDevServer extends DevServer {
478
480
  private async transformAndServe(filePath: string, urlPath: string): Promise<ResponseData> {
479
481
  try {
480
482
  const content = this.vfs.readFileSync(filePath, 'utf8');
483
+ const hash = simpleHash(content);
484
+
485
+ // Check transform cache
486
+ const cached = this.transformCache.get(filePath);
487
+ if (cached && cached.hash === hash) {
488
+ const buffer = Buffer.from(cached.code);
489
+ return {
490
+ statusCode: 200,
491
+ statusMessage: 'OK',
492
+ headers: {
493
+ 'Content-Type': 'application/javascript; charset=utf-8',
494
+ 'Content-Length': String(buffer.length),
495
+ 'Cache-Control': 'no-cache',
496
+ 'X-Transformed': 'true',
497
+ 'X-Cache': 'hit',
498
+ },
499
+ body: buffer,
500
+ };
501
+ }
502
+
481
503
  const transformed = await this.transformCode(content, urlPath);
482
504
 
505
+ // Cache the transform result
506
+ this.transformCache.set(filePath, { code: transformed, hash });
507
+
483
508
  const buffer = Buffer.from(transformed);
484
509
  return {
485
510
  statusCode: 200,
package/src/runtime.ts CHANGED
@@ -7,6 +7,8 @@
7
7
 
8
8
  import { VirtualFS } from './virtual-fs';
9
9
  import type { IRuntime, IExecuteResult, IRuntimeOptions } from './runtime-interface';
10
+ import type { PackageJson } from './types/package-json';
11
+ import { simpleHash } from './utils/hash';
10
12
  import { createFsShim, FsShim } from './shims/fs';
11
13
  import * as pathShim from './shims/path';
12
14
  import { createProcess, Process } from './shims/process';
@@ -347,8 +349,30 @@ function createRequire(
347
349
  process: Process,
348
350
  currentDir: string,
349
351
  moduleCache: Record<string, Module>,
350
- options: RuntimeOptions
352
+ options: RuntimeOptions,
353
+ processedCodeCache?: Map<string, string>
351
354
  ): RequireFunction {
355
+ // Module resolution cache for faster repeated imports
356
+ const resolutionCache: Map<string, string | null> = new Map();
357
+
358
+ // Package.json parsing cache
359
+ const packageJsonCache: Map<string, PackageJson | null> = new Map();
360
+
361
+ const getParsedPackageJson = (pkgPath: string): PackageJson | null => {
362
+ if (packageJsonCache.has(pkgPath)) {
363
+ return packageJsonCache.get(pkgPath)!;
364
+ }
365
+ try {
366
+ const content = vfs.readFileSync(pkgPath, 'utf8');
367
+ const parsed = JSON.parse(content) as PackageJson;
368
+ packageJsonCache.set(pkgPath, parsed);
369
+ return parsed;
370
+ } catch {
371
+ packageJsonCache.set(pkgPath, null);
372
+ return null;
373
+ }
374
+ };
375
+
352
376
  const resolveModule = (id: string, fromDir: string): string => {
353
377
  // Handle node: protocol prefix (Node.js 16+)
354
378
  if (id.startsWith('node:')) {
@@ -360,6 +384,16 @@ function createRequire(
360
384
  return id;
361
385
  }
362
386
 
387
+ // Check resolution cache
388
+ const cacheKey = `${fromDir}|${id}`;
389
+ const cached = resolutionCache.get(cacheKey);
390
+ if (cached !== undefined) {
391
+ if (cached === null) {
392
+ throw new Error(`Cannot find module '${id}'`);
393
+ }
394
+ return cached;
395
+ }
396
+
363
397
  // Relative paths
364
398
  if (id.startsWith('./') || id.startsWith('../') || id.startsWith('/')) {
365
399
  const resolved = id.startsWith('/')
@@ -370,11 +404,13 @@ function createRequire(
370
404
  if (vfs.existsSync(resolved)) {
371
405
  const stats = vfs.statSync(resolved);
372
406
  if (stats.isFile()) {
407
+ resolutionCache.set(cacheKey, resolved);
373
408
  return resolved;
374
409
  }
375
410
  // Directory - look for index.js
376
411
  const indexPath = pathShim.join(resolved, 'index.js');
377
412
  if (vfs.existsSync(indexPath)) {
413
+ resolutionCache.set(cacheKey, indexPath);
378
414
  return indexPath;
379
415
  }
380
416
  }
@@ -384,10 +420,12 @@ function createRequire(
384
420
  for (const ext of extensions) {
385
421
  const withExt = resolved + ext;
386
422
  if (vfs.existsSync(withExt)) {
423
+ resolutionCache.set(cacheKey, withExt);
387
424
  return withExt;
388
425
  }
389
426
  }
390
427
 
428
+ resolutionCache.set(cacheKey, null);
391
429
  throw new Error(`Cannot find module '${id}' from '${fromDir}'`);
392
430
  }
393
431
 
@@ -436,10 +474,8 @@ function createRequire(
436
474
  const pkgRoot = pathShim.join(nodeModulesDir, pkgName);
437
475
  const pkgPath = pathShim.join(pkgRoot, 'package.json');
438
476
 
439
- if (vfs.existsSync(pkgPath)) {
440
- const pkgContent = vfs.readFileSync(pkgPath, 'utf8');
441
- const pkg = JSON.parse(pkgContent);
442
-
477
+ const pkg = getParsedPackageJson(pkgPath);
478
+ if (pkg) {
443
479
  // Use resolve.exports to handle the exports field
444
480
  if (pkg.exports) {
445
481
  try {
@@ -474,15 +510,22 @@ function createRequire(
474
510
  while (searchDir !== '/') {
475
511
  const nodeModulesDir = pathShim.join(searchDir, 'node_modules');
476
512
  const resolved = tryResolveFromNodeModules(nodeModulesDir, id);
477
- if (resolved) return resolved;
513
+ if (resolved) {
514
+ resolutionCache.set(cacheKey, resolved);
515
+ return resolved;
516
+ }
478
517
 
479
518
  searchDir = pathShim.dirname(searchDir);
480
519
  }
481
520
 
482
521
  // Try root node_modules as last resort
483
522
  const rootResolved = tryResolveFromNodeModules('/node_modules', id);
484
- if (rootResolved) return rootResolved;
523
+ if (rootResolved) {
524
+ resolutionCache.set(cacheKey, rootResolved);
525
+ return rootResolved;
526
+ }
485
527
 
528
+ resolutionCache.set(cacheKey, null);
486
529
  throw new Error(`Cannot find module '${id}'`);
487
530
  };
488
531
 
@@ -514,28 +557,40 @@ function createRequire(
514
557
  }
515
558
 
516
559
  // Read and execute JS file
517
- let code = vfs.readFileSync(resolvedPath, 'utf8');
560
+ const rawCode = vfs.readFileSync(resolvedPath, 'utf8');
518
561
  const dirname = pathShim.dirname(resolvedPath);
519
562
 
520
- // Transform ESM to CJS if needed (for .mjs files or ESM that wasn't pre-transformed)
521
- // This handles files that weren't transformed during npm install
522
- // BUT skip .cjs files and already-bundled CJS code
523
- const isCjsFile = resolvedPath.endsWith('.cjs');
524
- const isAlreadyBundledCjs = code.startsWith('"use strict";\nvar __') ||
525
- code.startsWith("'use strict';\nvar __");
563
+ // Check processed code cache (useful for HMR when module cache is cleared but code hasn't changed)
564
+ // Use a simple hash of the content for cache key to handle content changes
565
+ const codeCacheKey = `${resolvedPath}|${simpleHash(rawCode)}`;
566
+ let code = processedCodeCache?.get(codeCacheKey);
567
+
568
+ if (!code) {
569
+ code = rawCode;
526
570
 
527
- const hasEsmImport = /\bimport\s+[\w{*'"]/m.test(code);
528
- const hasEsmExport = /\bexport\s+(?:default|const|let|var|function|class|{|\*)/m.test(code);
571
+ // Transform ESM to CJS if needed (for .mjs files or ESM that wasn't pre-transformed)
572
+ // This handles files that weren't transformed during npm install
573
+ // BUT skip .cjs files and already-bundled CJS code
574
+ const isCjsFile = resolvedPath.endsWith('.cjs');
575
+ const isAlreadyBundledCjs = code.startsWith('"use strict";\nvar __') ||
576
+ code.startsWith("'use strict';\nvar __");
529
577
 
530
- if (!isCjsFile && !isAlreadyBundledCjs) {
531
- if (resolvedPath.endsWith('.mjs') || resolvedPath.includes('/esm/') || hasEsmImport || hasEsmExport) {
532
- code = transformEsmToCjs(code, resolvedPath);
578
+ const hasEsmImport = /\bimport\s+[\w{*'"]/m.test(code);
579
+ const hasEsmExport = /\bexport\s+(?:default|const|let|var|function|class|{|\*)/m.test(code);
580
+
581
+ if (!isCjsFile && !isAlreadyBundledCjs) {
582
+ if (resolvedPath.endsWith('.mjs') || resolvedPath.includes('/esm/') || hasEsmImport || hasEsmExport) {
583
+ code = transformEsmToCjs(code, resolvedPath);
584
+ }
533
585
  }
534
- }
535
586
 
536
- // Transform dynamic imports: import('x') -> __dynamicImport('x')
537
- // This allows dynamic imports to work in our eval-based runtime
538
- code = transformDynamicImports(code);
587
+ // Transform dynamic imports: import('x') -> __dynamicImport('x')
588
+ // This allows dynamic imports to work in our eval-based runtime
589
+ code = transformDynamicImports(code);
590
+
591
+ // Cache the processed code
592
+ processedCodeCache?.set(codeCacheKey, code);
593
+ }
539
594
 
540
595
  // Create require for this module
541
596
  const moduleRequire = createRequire(
@@ -544,7 +599,8 @@ function createRequire(
544
599
  process,
545
600
  dirname,
546
601
  moduleCache,
547
- options
602
+ options,
603
+ processedCodeCache
548
604
  );
549
605
  moduleRequire.cache = moduleCache;
550
606
 
@@ -779,6 +835,8 @@ export class Runtime {
779
835
  private process: Process;
780
836
  private moduleCache: Record<string, Module> = {};
781
837
  private options: RuntimeOptions;
838
+ /** Cache for pre-processed code (after ESM transform) before eval */
839
+ private processedCodeCache: Map<string, string> = new Map();
782
840
 
783
841
  constructor(vfs: VirtualFS, options: RuntimeOptions = {}) {
784
842
  this.vfs = vfs;
@@ -907,7 +965,8 @@ export class Runtime {
907
965
  this.process,
908
966
  dirname,
909
967
  this.moduleCache,
910
- this.options
968
+ this.options,
969
+ this.processedCodeCache
911
970
  );
912
971
 
913
972
  // Create module object
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Type definition for package.json files
3
+ */
4
+ export interface PackageJson {
5
+ name?: string;
6
+ version?: string;
7
+ main?: string;
8
+ module?: string;
9
+ types?: string;
10
+ exports?: Record<string, unknown> | string;
11
+ dependencies?: Record<string, string>;
12
+ devDependencies?: Record<string, string>;
13
+ peerDependencies?: Record<string, string>;
14
+ [key: string]: unknown;
15
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Simple hash function for content-based cache invalidation.
3
+ * Uses djb2-style hashing for fast string hashing.
4
+ */
5
+ export function simpleHash(str: string): string {
6
+ let hash = 0;
7
+ for (let i = 0; i < str.length; i++) {
8
+ hash = ((hash << 5) - hash) + str.charCodeAt(i);
9
+ hash |= 0;
10
+ }
11
+ return hash.toString(36);
12
+ }