@zntc/wasm 0.1.6 → 0.1.7

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/README.md CHANGED
@@ -48,15 +48,23 @@ const result = transpile('const x: number = 1;', { filename: 'input.ts' });
48
48
  ### Bundler build
49
49
 
50
50
  ```ts
51
- import { build, initBundler, bundlerLastErrorMessage } from '@zntc/wasm';
51
+ import { build, initBundler, bundlerLastErrorMessage, VirtualFileSystem } from '@zntc/wasm';
52
52
  import wasmUrl from '@zntc/wasm/zntc-bundler.wasm?url';
53
53
 
54
- await initBundler(wasmUrl); // separate from init() used for transpile
55
- const out = build('/main.ts', { format: 'esm', target: 'es2020' });
54
+ // The bundler reads a VFS instead of a real file system. Imports in the entry are
55
+ // resolved recursively against the paths registered here.
56
+ const vfs = new VirtualFileSystem();
57
+ vfs.set('/src/util.ts', 'export const scale = (n: number) => n * 2;');
58
+ vfs.set('/src/main.ts', `import { scale } from './util'; export const x = scale(21);`);
59
+
60
+ await initBundler(vfs, wasmUrl); // separate from init() used for transpile
61
+ const out = build('/src/main.ts', { format: 'esm', target: 'es2020' });
56
62
  if (out === null) throw new Error(bundlerLastErrorMessage());
57
63
  ```
58
64
 
59
- `build` is synchronous and returns `null` on failure — call `bundlerLastErrorMessage()` to read the last error.
65
+ `build` is synchronous and returns `null` on failure — call `bundlerLastErrorMessage()` to read the last error. When the build produces error diagnostics (an unresolvable import, for example) it returns `null` rather than partial output — the same contract as the CLI ("skip output and exit 1 on errors").
66
+
67
+ A VFS holds files only; directories exist as path prefixes. To back it with a lazy source (network, IndexedDB), subclass `VirtualFileSystem` and override `get` / `has` / `paths` (and `listDir` / `isDir` if needed).
60
68
 
61
69
  ## `@zntc/core` vs `@zntc/wasm`
62
70
 
package/dist/index.js CHANGED
@@ -288,6 +288,18 @@ function transpile(source, options = {}) {
288
288
  wasm.dealloc(optsPtr, optsLen);
289
289
  }
290
290
  }
291
+ var VFS_KIND_FILE = 0;
292
+ var VFS_KIND_DIRECTORY = 1;
293
+ function dirPrefix(dir) {
294
+ if (dir === "" || dir === ".")
295
+ return "";
296
+ const trimmed = dir.endsWith("/") && dir.length > 1 ? dir.slice(0, -1) : dir;
297
+ if (trimmed === "/")
298
+ return "/";
299
+ if (trimmed === ".")
300
+ return "";
301
+ return `${trimmed}/`;
302
+ }
291
303
 
292
304
  class VirtualFileSystem {
293
305
  files = new Map;
@@ -307,6 +319,39 @@ class VirtualFileSystem {
307
319
  paths() {
308
320
  return this.files.keys();
309
321
  }
322
+ isDir(dir) {
323
+ const prefix = dirPrefix(dir);
324
+ if (prefix.length === 0)
325
+ return true;
326
+ for (const path of this.paths()) {
327
+ if (path.startsWith(prefix))
328
+ return true;
329
+ }
330
+ return false;
331
+ }
332
+ listDir(dir) {
333
+ const prefix = dirPrefix(dir);
334
+ const files = [];
335
+ const dirs = new Set;
336
+ for (const path of this.paths()) {
337
+ if (prefix.length > 0 && !path.startsWith(prefix))
338
+ continue;
339
+ const rest = path.slice(prefix.length);
340
+ if (rest.length === 0)
341
+ continue;
342
+ const slash = rest.indexOf("/");
343
+ if (slash === -1)
344
+ files.push(rest);
345
+ else if (slash > 0)
346
+ dirs.add(rest.slice(0, slash));
347
+ }
348
+ if (files.length === 0 && dirs.size === 0)
349
+ return null;
350
+ const entries = files.map((name) => ({ name, kind: VFS_KIND_FILE }));
351
+ for (const name of dirs)
352
+ entries.push({ name, kind: VFS_KIND_DIRECTORY });
353
+ return entries;
354
+ }
310
355
  size() {
311
356
  return this.files.size;
312
357
  }
@@ -345,27 +390,36 @@ function createBundlerImports(memory) {
345
390
  statFile(pathPtr, pathLen, outSize, outKind, outMtimeLo, outMtimeHi) {
346
391
  const path = readBundlerString(pathPtr, pathLen);
347
392
  const data = bundlerVfs?.get(path);
348
- if (!data)
393
+ const isDir = !data && (bundlerVfs?.isDir(path) ?? false);
394
+ if (!data && !isDir)
349
395
  return 1;
350
396
  const view = new DataView(bundlerMemory.buffer);
351
- view.setBigUint64(outSize, BigInt(data.length), true);
352
- new Uint8Array(bundlerMemory.buffer, outKind, 1)[0] = 0;
397
+ view.setBigUint64(outSize, BigInt(data?.length ?? 0), true);
398
+ new Uint8Array(bundlerMemory.buffer, outKind, 1)[0] = isDir ? VFS_KIND_DIRECTORY : VFS_KIND_FILE;
353
399
  view.setBigUint64(outMtimeLo, 0n, true);
354
400
  view.setBigUint64(outMtimeHi, 0n, true);
355
401
  return 0;
356
402
  },
357
403
  access(pathPtr, pathLen) {
358
404
  const path = readBundlerString(pathPtr, pathLen);
359
- return bundlerVfs?.has(path) ? 0 : 1;
405
+ if (!bundlerVfs)
406
+ return 1;
407
+ return bundlerVfs.has(path) || bundlerVfs.isDir(path) ? 0 : 1;
360
408
  },
361
409
  realpath(pathPtr, pathLen) {
362
410
  const path = readBundlerString(pathPtr, pathLen);
363
- if (!bundlerVfs?.has(path))
411
+ if (!bundlerVfs)
412
+ return 0n;
413
+ if (!bundlerVfs.has(path) && !bundlerVfs.isDir(path))
364
414
  return 0n;
365
415
  return packBytes(encoder.encode(path));
366
416
  },
367
- listDir(_pathPtr, _pathLen) {
368
- return 0n;
417
+ listDir(pathPtr, pathLen) {
418
+ const path = readBundlerString(pathPtr, pathLen);
419
+ const entries = bundlerVfs?.listDir(path);
420
+ if (!entries || entries.length === 0)
421
+ return 0n;
422
+ return packBytes(encoder.encode(JSON.stringify(entries)));
369
423
  },
370
424
  hostFreeBytes(ptr, len) {
371
425
  bundler?.dealloc(ptr, len);
@@ -14,6 +14,10 @@ import type { Target, TranspileOptions, TranspileResult } from '../shared/index'
14
14
  export declare function init(input?: URL | string | Request | Response | BufferSource | WebAssembly.Module): Promise<void>;
15
15
  export declare function initSync(input: WebAssembly.Module | BufferSource): void;
16
16
  export declare function transpile(source: string, options?: TranspileOptions): TranspileResult;
17
+ export interface VfsDirEntry {
18
+ name: string;
19
+ kind: number;
20
+ }
17
21
  export declare class VirtualFileSystem {
18
22
  private files;
19
23
  set(path: string, content: string | Uint8Array): void;
@@ -21,6 +25,8 @@ export declare class VirtualFileSystem {
21
25
  has(path: string): boolean;
22
26
  delete(path: string): boolean;
23
27
  paths(): IterableIterator<string>;
28
+ isDir(dir: string): boolean;
29
+ listDir(dir: string): VfsDirEntry[] | null;
24
30
  size(): number;
25
31
  clear(): void;
26
32
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zntc/wasm",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "ZNTC native transpiler & compiler — WASM build",
5
5
  "keywords": [
6
6
  "browser",
package/zntc-bundler.wasm CHANGED
Binary file