taglib-wasm 2.2.2 → 2.3.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.
Files changed (87) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +197 -16
  3. package/dist/index.browser.d.ts +24 -4
  4. package/dist/index.browser.d.ts.map +1 -1
  5. package/dist/index.browser.js +1139 -217
  6. package/dist/index.d.ts +3 -2
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +2 -0
  9. package/dist/simple.browser.js +539 -209
  10. package/dist/src/constants/properties.d.ts +2 -2
  11. package/dist/src/constants/specialized-properties.d.ts +2 -2
  12. package/dist/src/constants/specialized-properties.js +2 -2
  13. package/dist/src/errors/base.d.ts +17 -2
  14. package/dist/src/errors/base.d.ts.map +1 -1
  15. package/dist/src/errors/base.js +18 -0
  16. package/dist/src/runtime/detector.d.ts +16 -1
  17. package/dist/src/runtime/detector.d.ts.map +1 -1
  18. package/dist/src/runtime/detector.js +58 -52
  19. package/dist/src/runtime/platform-io.d.ts +8 -0
  20. package/dist/src/runtime/platform-io.d.ts.map +1 -1
  21. package/dist/src/runtime/platform-io.js +11 -11
  22. package/dist/src/runtime/unified-loader/module-selection.d.ts +2 -2
  23. package/dist/src/runtime/unified-loader/module-selection.d.ts.map +1 -1
  24. package/dist/src/runtime/unified-loader/module-selection.js +3 -5
  25. package/dist/src/runtime/wasi-adapter/adapter.d.ts +13 -1
  26. package/dist/src/runtime/wasi-adapter/adapter.d.ts.map +1 -1
  27. package/dist/src/runtime/wasi-adapter/adapter.js +17 -0
  28. package/dist/src/runtime/wasi-adapter/audio-properties.d.ts +4 -1
  29. package/dist/src/runtime/wasi-adapter/audio-properties.d.ts.map +1 -1
  30. package/dist/src/runtime/wasi-adapter/audio-properties.js +24 -6
  31. package/dist/src/runtime/wasi-adapter/path-open.d.ts +68 -0
  32. package/dist/src/runtime/wasi-adapter/path-open.d.ts.map +1 -0
  33. package/dist/src/runtime/wasi-adapter/path-open.js +76 -0
  34. package/dist/src/runtime/wasi-adapter/wasm-io.d.ts.map +1 -1
  35. package/dist/src/runtime/wasi-adapter/wasm-io.js +36 -28
  36. package/dist/src/runtime/wasi-host-loader.js +8 -3
  37. package/dist/src/runtime/wasmer-sdk-loader/types.d.ts +13 -0
  38. package/dist/src/runtime/wasmer-sdk-loader/types.d.ts.map +1 -1
  39. package/dist/src/simple/checksum-operations.d.ts +25 -0
  40. package/dist/src/simple/checksum-operations.d.ts.map +1 -0
  41. package/dist/src/simple/checksum-operations.js +7 -0
  42. package/dist/src/simple/index.d.ts +2 -0
  43. package/dist/src/simple/index.d.ts.map +1 -1
  44. package/dist/src/simple/index.js +2 -0
  45. package/dist/src/taglib/audio-file-checksum.d.ts +47 -0
  46. package/dist/src/taglib/audio-file-checksum.d.ts.map +1 -0
  47. package/dist/src/taglib/audio-file-checksum.js +77 -0
  48. package/dist/src/taglib/audio-file-impl.d.ts +4 -0
  49. package/dist/src/taglib/audio-file-impl.d.ts.map +1 -1
  50. package/dist/src/taglib/audio-file-impl.js +34 -2
  51. package/dist/src/taglib/audio-file-interface.d.ts +17 -0
  52. package/dist/src/taglib/audio-file-interface.d.ts.map +1 -1
  53. package/dist/src/taglib/embind-adapter.d.ts.map +1 -1
  54. package/dist/src/taglib/embind-adapter.js +4 -1
  55. package/dist/src/taglib/id3v2-frames.d.ts.map +1 -1
  56. package/dist/src/taglib/id3v2-frames.js +2 -2
  57. package/dist/src/taglib/media-ranges.d.ts +85 -0
  58. package/dist/src/taglib/media-ranges.d.ts.map +1 -0
  59. package/dist/src/taglib/media-ranges.js +192 -0
  60. package/dist/src/taglib/metadata-extent.d.ts +55 -0
  61. package/dist/src/taglib/metadata-extent.d.ts.map +1 -1
  62. package/dist/src/taglib/metadata-extent.js +24 -6
  63. package/dist/src/taglib/taglib-class.d.ts.map +1 -1
  64. package/dist/src/taglib/taglib-class.js +13 -24
  65. package/dist/src/types/audio-formats.d.ts +5 -5
  66. package/dist/src/types/audio-formats.d.ts.map +1 -1
  67. package/dist/src/types/format-property-keys.d.ts +1 -1
  68. package/dist/src/types/format-property-keys.d.ts.map +1 -1
  69. package/dist/src/types/tags.d.ts +8 -1
  70. package/dist/src/types/tags.d.ts.map +1 -1
  71. package/dist/src/utils/path.d.ts +12 -0
  72. package/dist/src/utils/path.d.ts.map +1 -1
  73. package/dist/src/utils/path.js +19 -0
  74. package/dist/src/utils/tag-mapping.d.ts.map +1 -1
  75. package/dist/src/utils/tag-mapping.js +2 -0
  76. package/dist/src/version.d.ts +1 -1
  77. package/dist/src/version.js +1 -1
  78. package/dist/src/wasm.d.ts +9 -0
  79. package/dist/src/wasm.d.ts.map +1 -1
  80. package/dist/src/web-utils/data-url.d.ts.map +1 -1
  81. package/dist/src/web-utils/data-url.js +4 -2
  82. package/dist/taglib-wasi.wasm +0 -0
  83. package/dist/taglib-web.wasm +0 -0
  84. package/dist/web.browser.d.ts +13 -0
  85. package/dist/web.browser.d.ts.map +1 -0
  86. package/dist/web.browser.js +3630 -0
  87. package/package.json +19 -17
@@ -299,7 +299,7 @@ export declare const PROPERTIES: {
299
299
  };
300
300
  readonly releaseType: {
301
301
  readonly key: "RELEASETYPE";
302
- readonly description: "Release type (album, single, EP, compilation, ...). Multi-value (e.g. 'album' + 'EP'). TagLib 2.3.1 translates the RELEASETYPE key per format: ID3v2 TXXX 'MUSICBRAINZ ALBUM TYPE' (TagLib's description casing), MP4 freeform atom, APEv2 MUSICBRAINZ_ALBUMTYPE, ASF 'MusicBrainz/Album Type', Vorbis/Matroska raw RELEASETYPE";
302
+ readonly description: "Release type (album, single, EP, compilation, ...). Multi-value (e.g. 'album' + 'EP'). TagLib 2.3.2 translates the RELEASETYPE key per format: ID3v2 TXXX 'MUSICBRAINZ ALBUM TYPE' (TagLib's description casing), MP4 freeform atom, APEv2 MUSICBRAINZ_ALBUMTYPE, ASF 'MusicBrainz/Album Type', Vorbis/Matroska raw RELEASETYPE";
303
303
  readonly type: "string";
304
304
  readonly supportedFormats: readonly ["ID3v2", "MP4", "Vorbis", "APE", "ASF", "Matroska"];
305
305
  readonly mappings: {
@@ -313,7 +313,7 @@ export declare const PROPERTIES: {
313
313
  };
314
314
  readonly releaseCountry: {
315
315
  readonly key: "RELEASECOUNTRY";
316
- readonly description: "Release country (ISO 3166-1 code, e.g. 'US'). TagLib 2.3.1 translates the RELEASECOUNTRY key per format: ID3v2 TXXX 'MUSICBRAINZ ALBUM RELEASE COUNTRY' (TagLib's description casing; an uppercase TXXX:RELEASECOUNTRY description also reads back), MP4 freeform atom 'MusicBrainz Album Release Country', APEv2 raw RELEASECOUNTRY, ASF 'MusicBrainz/Album Release Country', WAV ICNT, Vorbis/Matroska raw RELEASECOUNTRY";
316
+ readonly description: "Release country (ISO 3166-1 code, e.g. 'US'). TagLib 2.3.2 translates the RELEASECOUNTRY key per format: ID3v2 TXXX 'MUSICBRAINZ ALBUM RELEASE COUNTRY' (TagLib's description casing; an uppercase TXXX:RELEASECOUNTRY description also reads back), MP4 freeform atom 'MusicBrainz Album Release Country', APEv2 raw RELEASECOUNTRY, ASF 'MusicBrainz/Album Release Country', WAV ICNT, Vorbis/Matroska raw RELEASECOUNTRY";
317
317
  readonly type: "string";
318
318
  readonly supportedFormats: readonly ["ID3v2", "MP4", "Vorbis", "APE", "ASF", "Matroska", "WAV"];
319
319
  readonly mappings: {
@@ -61,7 +61,7 @@ export declare const SPECIALIZED_PROPERTIES: {
61
61
  };
62
62
  readonly releaseType: {
63
63
  readonly key: "RELEASETYPE";
64
- readonly description: "Release type (album, single, EP, compilation, ...). Multi-value (e.g. 'album' + 'EP'). TagLib 2.3.1 translates the RELEASETYPE key per format: ID3v2 TXXX 'MUSICBRAINZ ALBUM TYPE' (TagLib's description casing), MP4 freeform atom, APEv2 MUSICBRAINZ_ALBUMTYPE, ASF 'MusicBrainz/Album Type', Vorbis/Matroska raw RELEASETYPE";
64
+ readonly description: "Release type (album, single, EP, compilation, ...). Multi-value (e.g. 'album' + 'EP'). TagLib 2.3.2 translates the RELEASETYPE key per format: ID3v2 TXXX 'MUSICBRAINZ ALBUM TYPE' (TagLib's description casing), MP4 freeform atom, APEv2 MUSICBRAINZ_ALBUMTYPE, ASF 'MusicBrainz/Album Type', Vorbis/Matroska raw RELEASETYPE";
65
65
  readonly type: "string";
66
66
  readonly supportedFormats: readonly ["ID3v2", "MP4", "Vorbis", "APE", "ASF", "Matroska"];
67
67
  readonly mappings: {
@@ -75,7 +75,7 @@ export declare const SPECIALIZED_PROPERTIES: {
75
75
  };
76
76
  readonly releaseCountry: {
77
77
  readonly key: "RELEASECOUNTRY";
78
- readonly description: "Release country (ISO 3166-1 code, e.g. 'US'). TagLib 2.3.1 translates the RELEASECOUNTRY key per format: ID3v2 TXXX 'MUSICBRAINZ ALBUM RELEASE COUNTRY' (TagLib's description casing; an uppercase TXXX:RELEASECOUNTRY description also reads back), MP4 freeform atom 'MusicBrainz Album Release Country', APEv2 raw RELEASECOUNTRY, ASF 'MusicBrainz/Album Release Country', WAV ICNT, Vorbis/Matroska raw RELEASECOUNTRY";
78
+ readonly description: "Release country (ISO 3166-1 code, e.g. 'US'). TagLib 2.3.2 translates the RELEASECOUNTRY key per format: ID3v2 TXXX 'MUSICBRAINZ ALBUM RELEASE COUNTRY' (TagLib's description casing; an uppercase TXXX:RELEASECOUNTRY description also reads back), MP4 freeform atom 'MusicBrainz Album Release Country', APEv2 raw RELEASECOUNTRY, ASF 'MusicBrainz/Album Release Country', WAV ICNT, Vorbis/Matroska raw RELEASECOUNTRY";
79
79
  readonly type: "string";
80
80
  readonly supportedFormats: readonly ["ID3v2", "MP4", "Vorbis", "APE", "ASF", "Matroska", "WAV"];
81
81
  readonly mappings: {
@@ -46,7 +46,7 @@ const SPECIALIZED_PROPERTIES = {
46
46
  },
47
47
  releaseType: {
48
48
  key: "RELEASETYPE",
49
- description: "Release type (album, single, EP, compilation, ...). Multi-value (e.g. 'album' + 'EP'). TagLib 2.3.1 translates the RELEASETYPE key per format: ID3v2 TXXX 'MUSICBRAINZ ALBUM TYPE' (TagLib's description casing), MP4 freeform atom, APEv2 MUSICBRAINZ_ALBUMTYPE, ASF 'MusicBrainz/Album Type', Vorbis/Matroska raw RELEASETYPE",
49
+ description: "Release type (album, single, EP, compilation, ...). Multi-value (e.g. 'album' + 'EP'). TagLib 2.3.2 translates the RELEASETYPE key per format: ID3v2 TXXX 'MUSICBRAINZ ALBUM TYPE' (TagLib's description casing), MP4 freeform atom, APEv2 MUSICBRAINZ_ALBUMTYPE, ASF 'MusicBrainz/Album Type', Vorbis/Matroska raw RELEASETYPE",
50
50
  type: "string",
51
51
  supportedFormats: [
52
52
  "ID3v2",
@@ -64,7 +64,7 @@ const SPECIALIZED_PROPERTIES = {
64
64
  },
65
65
  releaseCountry: {
66
66
  key: "RELEASECOUNTRY",
67
- description: "Release country (ISO 3166-1 code, e.g. 'US'). TagLib 2.3.1 translates the RELEASECOUNTRY key per format: ID3v2 TXXX 'MUSICBRAINZ ALBUM RELEASE COUNTRY' (TagLib's description casing; an uppercase TXXX:RELEASECOUNTRY description also reads back), MP4 freeform atom 'MusicBrainz Album Release Country', APEv2 raw RELEASECOUNTRY, ASF 'MusicBrainz/Album Release Country', WAV ICNT, Vorbis/Matroska raw RELEASECOUNTRY",
67
+ description: "Release country (ISO 3166-1 code, e.g. 'US'). TagLib 2.3.2 translates the RELEASECOUNTRY key per format: ID3v2 TXXX 'MUSICBRAINZ ALBUM RELEASE COUNTRY' (TagLib's description casing; an uppercase TXXX:RELEASECOUNTRY description also reads back), MP4 freeform atom 'MusicBrainz Album Release Country', APEv2 raw RELEASECOUNTRY, ASF 'MusicBrainz/Album Release Country', WAV ICNT, Vorbis/Matroska raw RELEASECOUNTRY",
68
68
  type: "string",
69
69
  supportedFormats: [
70
70
  "ID3v2",
@@ -1,7 +1,22 @@
1
1
  /**
2
- * List of audio formats supported by TagLib-Wasm
2
+ * List of audio formats supported by TagLib-Wasm.
3
+ *
4
+ * The prose source of truth is the README's "Supported Formats" section; this
5
+ * list carries every `FileType` member except `"unknown"` (src/types/audio-
6
+ * formats.ts), plus the extension aliases files actually carry ("M4A", "MKA")
7
+ * — ASF is the container of the WMA flavour the README names.
8
+ *
9
+ * Public contract: the default `supportedFormats` on `UnsupportedFormatError`
10
+ * (src/errors/classes.ts), and part of that error's message.
11
+ *
12
+ * This is the formats the library can read, not a promise that both backends
13
+ * describe all of them identically. Measured 2026-09-18 (taglib-uat8):
14
+ * `getFormat()` answers every member on both backends, but on Emscripten
15
+ * `audioProperties().containerFormat` / `.codec` still report `"unknown"` for
16
+ * the formats the embind sniffer cannot place (APE, DSF, DSDIFF, MPC, SHN,
17
+ * MOD, S3M, IT, XM); their tags and the rest of their properties load.
3
18
  */
4
- export declare const SUPPORTED_FORMATS: readonly ["MP3", "MP4", "M4A", "FLAC", "OGG", "WAV", "MKA"];
19
+ export declare const SUPPORTED_FORMATS: readonly ["MP3", "AAC", "MP4", "M4A", "FLAC", "OGG", "OPUS", "OggFLAC", "SPEEX", "WAV", "AIFF", "ASF", "APE", "DSF", "DSDIFF", "WV", "MPC", "TTA", "SHN", "MOD", "S3M", "IT", "XM", "MATROSKA", "MKA"];
5
20
  /**
6
21
  * Error codes for programmatic error handling
7
22
  */
@@ -1 +1 @@
1
- {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/errors/base.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,iBAAiB,6DAQpB,CAAC;AAEX;;GAEG;AACH,MAAM,MAAM,eAAe,GACvB,gBAAgB,GAChB,gBAAgB,GAChB,oBAAoB,GACpB,gBAAgB,GAChB,UAAU,GACV,QAAQ,GACR,aAAa,GACb,aAAa,GACb,aAAa,GACb,WAAW,CAAC;AAEhB;;GAEG;AACH,qBAAa,WAAY,SAAQ,KAAK;aAQlB,IAAI,EAAE,eAAe;aAErB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IATnD;;;;;OAKG;gBAEe,IAAI,EAAE,eAAe,EACrC,OAAO,EAAE,MAAM,EACC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,YAAA;CAMpD"}
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/errors/base.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,iBAAiB,wMA0BpB,CAAC;AAEX;;GAEG;AACH,MAAM,MAAM,eAAe,GACvB,gBAAgB,GAChB,gBAAgB,GAChB,oBAAoB,GACpB,gBAAgB,GAChB,UAAU,GACV,QAAQ,GACR,aAAa,GACb,aAAa,GACb,aAAa,GACb,WAAW,CAAC;AAEhB;;GAEG;AACH,qBAAa,WAAY,SAAQ,KAAK;aAQlB,IAAI,EAAE,eAAe;aAErB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IATnD;;;;;OAKG;gBAEe,IAAI,EAAE,eAAe,EACrC,OAAO,EAAE,MAAM,EACC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,YAAA;CAMpD"}
@@ -3,11 +3,29 @@ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { en
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
4
  const SUPPORTED_FORMATS = [
5
5
  "MP3",
6
+ "AAC",
6
7
  "MP4",
7
8
  "M4A",
8
9
  "FLAC",
9
10
  "OGG",
11
+ "OPUS",
12
+ "OggFLAC",
13
+ "SPEEX",
10
14
  "WAV",
15
+ "AIFF",
16
+ "ASF",
17
+ "APE",
18
+ "DSF",
19
+ "DSDIFF",
20
+ "WV",
21
+ "MPC",
22
+ "TTA",
23
+ "SHN",
24
+ "MOD",
25
+ "S3M",
26
+ "IT",
27
+ "XM",
28
+ "MATROSKA",
11
29
  "MKA"
12
30
  ];
13
31
  class TagLibError extends Error {
@@ -7,6 +7,21 @@ export interface RuntimeDetectionResult {
7
7
  supportsStreaming: boolean;
8
8
  performanceTier: 1 | 2 | 3;
9
9
  }
10
+ /**
11
+ * The pure per-environment backend configuration. `detectRuntime()` is the
12
+ * only sniffer in the codebase; every downstream decision (backend choice,
13
+ * PlatformIO creation, WASI availability) derives from this table so it can
14
+ * be exercised with synthetic environments instead of real runtimes
15
+ * (taglib-2b4).
16
+ */
17
+ export interface EnvironmentProfile {
18
+ wasmType: WasmBinaryType;
19
+ supportsFilesystem: boolean;
20
+ supportsStreaming: boolean;
21
+ performanceTier: 1 | 2 | 3;
22
+ }
23
+ /** Pure environment -> backend configuration lookup (taglib-2b4). */
24
+ export declare function environmentProfile(env: RuntimeEnvironment): EnvironmentProfile;
10
25
  /**
11
26
  * Check if a Node.js version meets the minimum requirement (v22.6.0+).
12
27
  * Returns an error message string if the version is too old, or undefined if OK.
@@ -22,5 +37,5 @@ export declare function detectRuntime(): RuntimeDetectionResult;
22
37
  */
23
38
  export declare function supportsExnref(): boolean;
24
39
  export declare function getEnvironmentDescription(env: RuntimeEnvironment): string;
25
- export declare function canLoadWasmType(wasmType: WasmBinaryType): boolean;
40
+ export declare function canLoadWasmType(wasmType: WasmBinaryType, env?: RuntimeEnvironment): boolean;
26
41
  //# sourceMappingURL=detector.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"detector.d.ts","sourceRoot":"","sources":["../../../src/runtime/detector.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAC1B,WAAW,GACX,WAAW,GACX,UAAU,GACV,SAAS,GACT,iBAAiB,GACjB,QAAQ,GACR,YAAY,CAAC;AAEjB,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,YAAY,CAAC;AAEnD,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,kBAAkB,CAAC;IAChC,QAAQ,EAAE,cAAc,CAAC;IACzB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,eAAe,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;CAC5B;AAOD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,MAAM,GAAG,SAAS,GAC9B,MAAM,GAAG,SAAS,CAepB;AAuCD,qFAAqF;AACrF,wBAAgB,MAAM,IAAI,OAAO,CAEhC;AAED,wBAAgB,aAAa,IAAI,sBAAsB,CA8EtD;AAWD;;;GAGG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAMxC;AAED,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,kBAAkB,GAAG,MAAM,CAmBzE;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,cAAc,GAAG,OAAO,CAQjE"}
1
+ {"version":3,"file":"detector.d.ts","sourceRoot":"","sources":["../../../src/runtime/detector.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAC1B,WAAW,GACX,WAAW,GACX,UAAU,GACV,SAAS,GACT,iBAAiB,GACjB,QAAQ,GACR,YAAY,CAAC;AAEjB,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,YAAY,CAAC;AAEnD,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,kBAAkB,CAAC;IAChC,QAAQ,EAAE,cAAc,CAAC;IACzB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,eAAe,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;CAC5B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,cAAc,CAAC;IACzB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,eAAe,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;CAC5B;AA+CD,qEAAqE;AACrE,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,kBAAkB,GACtB,kBAAkB,CAEpB;AAOD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,MAAM,GAAG,SAAS,GAC9B,MAAM,GAAG,SAAS,CAepB;AAuCD,qFAAqF;AACrF,wBAAgB,MAAM,IAAI,OAAO,CAEhC;AAED,wBAAgB,aAAa,IAAI,sBAAsB,CAuCtD;AAWD;;;GAGG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAMxC;AAED,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,kBAAkB,GAAG,MAAM,CAmBzE;AAED,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,cAAc,EACxB,GAAG,GAAE,kBAAgD,GACpD,OAAO,CAKT"}
@@ -1,3 +1,50 @@
1
+ const ENVIRONMENT_PROFILES = {
2
+ "deno-wasi": {
3
+ wasmType: "wasi",
4
+ supportsFilesystem: true,
5
+ supportsStreaming: true,
6
+ performanceTier: 1
7
+ },
8
+ "node-wasi": {
9
+ wasmType: "wasi",
10
+ supportsFilesystem: true,
11
+ supportsStreaming: true,
12
+ performanceTier: 1
13
+ },
14
+ "bun-wasi": {
15
+ wasmType: "wasi",
16
+ supportsFilesystem: true,
17
+ supportsStreaming: true,
18
+ performanceTier: 1
19
+ },
20
+ browser: {
21
+ wasmType: "emscripten",
22
+ supportsFilesystem: false,
23
+ supportsStreaming: true,
24
+ performanceTier: 2
25
+ },
26
+ worker: {
27
+ wasmType: "emscripten",
28
+ supportsFilesystem: false,
29
+ supportsStreaming: true,
30
+ performanceTier: 2
31
+ },
32
+ cloudflare: {
33
+ wasmType: "emscripten",
34
+ supportsFilesystem: false,
35
+ supportsStreaming: false,
36
+ performanceTier: 3
37
+ },
38
+ "node-emscripten": {
39
+ wasmType: "emscripten",
40
+ supportsFilesystem: true,
41
+ supportsStreaming: true,
42
+ performanceTier: 3
43
+ }
44
+ };
45
+ function environmentProfile(env) {
46
+ return ENVIRONMENT_PROFILES[env];
47
+ }
1
48
  const g = globalThis;
2
49
  const MIN_NODE_MAJOR = 22;
3
50
  const MIN_NODE_MINOR = 6;
@@ -38,73 +85,32 @@ function isDeno() {
38
85
  }
39
86
  function detectRuntime() {
40
87
  if (isDeno() && hasWASISupport()) {
41
- return {
42
- environment: "deno-wasi",
43
- wasmType: "wasi",
44
- supportsFilesystem: true,
45
- supportsStreaming: true,
46
- performanceTier: 1
47
- };
88
+ return { environment: "deno-wasi", ...environmentProfile("deno-wasi") };
48
89
  }
49
90
  if (isBun()) {
50
- return {
51
- environment: "bun-wasi",
52
- wasmType: "wasi",
53
- supportsFilesystem: true,
54
- supportsStreaming: true,
55
- performanceTier: 1
56
- };
91
+ return { environment: "bun-wasi", ...environmentProfile("bun-wasi") };
57
92
  }
58
93
  if (isNode() && hasWASISupport()) {
59
- return {
60
- environment: "node-wasi",
61
- wasmType: "wasi",
62
- supportsFilesystem: true,
63
- supportsStreaming: true,
64
- performanceTier: 1
65
- };
94
+ return { environment: "node-wasi", ...environmentProfile("node-wasi") };
66
95
  }
67
96
  if (isBrowser()) {
68
- return {
69
- environment: "browser",
70
- wasmType: "emscripten",
71
- supportsFilesystem: false,
72
- supportsStreaming: true,
73
- performanceTier: 2
74
- };
97
+ return { environment: "browser", ...environmentProfile("browser") };
75
98
  }
76
99
  if (isWebWorker()) {
77
- return {
78
- environment: "worker",
79
- wasmType: "emscripten",
80
- supportsFilesystem: false,
81
- supportsStreaming: true,
82
- performanceTier: 2
83
- };
100
+ return { environment: "worker", ...environmentProfile("worker") };
84
101
  }
85
102
  if (isCloudflareWorker()) {
86
- return {
87
- environment: "cloudflare",
88
- wasmType: "emscripten",
89
- supportsFilesystem: false,
90
- supportsStreaming: false,
91
- performanceTier: 3
92
- };
103
+ return { environment: "cloudflare", ...environmentProfile("cloudflare") };
93
104
  }
94
105
  if (isNode()) {
95
106
  return {
96
107
  environment: "node-emscripten",
97
- wasmType: "emscripten",
98
- supportsFilesystem: true,
99
- supportsStreaming: true,
100
- performanceTier: 3
108
+ ...environmentProfile("node-emscripten")
101
109
  };
102
110
  }
103
111
  return {
104
112
  environment: "browser",
105
- wasmType: "emscripten",
106
- supportsFilesystem: false,
107
- supportsStreaming: true,
113
+ ...environmentProfile("browser"),
108
114
  performanceTier: 3
109
115
  };
110
116
  }
@@ -158,10 +164,9 @@ function getEnvironmentDescription(env) {
158
164
  return "Unknown environment";
159
165
  }
160
166
  }
161
- function canLoadWasmType(wasmType) {
162
- const result = detectRuntime();
167
+ function canLoadWasmType(wasmType, env = detectRuntime().environment) {
163
168
  if (wasmType === "wasi") {
164
- return result.environment === "deno-wasi" || result.environment === "node-wasi" || result.environment === "bun-wasi";
169
+ return environmentProfile(env).wasmType === "wasi";
165
170
  }
166
171
  return true;
167
172
  }
@@ -169,6 +174,7 @@ export {
169
174
  canLoadWasmType,
170
175
  checkNodeVersion,
171
176
  detectRuntime,
177
+ environmentProfile,
172
178
  getEnvironmentDescription,
173
179
  isDeno,
174
180
  supportsExnref
@@ -1,3 +1,4 @@
1
+ import { type RuntimeEnvironment } from "./detector.js";
1
2
  export type PlatformIO = {
2
3
  readFile(path: string): Promise<Uint8Array>;
3
4
  writeFile(path: string, data: Uint8Array): Promise<void>;
@@ -11,6 +12,13 @@ export type PlatformIO = {
11
12
  }>;
12
13
  readPartial?: (path: string, headerSize: number, footerSize: number) => Promise<Uint8Array>;
13
14
  };
15
+ /**
16
+ * Pure environment -> PlatformIO selection (taglib-2b4): each environment's
17
+ * factory is chosen without sniffing, so the routing is testable with a
18
+ * synthetic environment. Factories are lazy — nothing touches the runtime
19
+ * until a method is called, so calling this under any runtime is safe.
20
+ */
21
+ export declare function createPlatformIOFor(env: RuntimeEnvironment): PlatformIO;
14
22
  export declare function getPlatformIO(): PlatformIO;
15
23
  /** @internal */
16
24
  export declare function _setPlatformIOForTesting(io: PlatformIO): void;
@@ -1 +1 @@
1
- {"version":3,"file":"platform-io.d.ts","sourceRoot":"","sources":["../../../src/runtime/platform-io.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC5C,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9C,OAAO,CACL,IAAI,EAAE,MAAM,GACX,cAAc,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAC3E,WAAW,CAAC,EAAE,CACZ,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,KACf,OAAO,CAAC,UAAU,CAAC,CAAC;CAC1B,CAAC;AA0LF,wBAAgB,aAAa,IAAI,UAAU,CAyB1C;AAED,gBAAgB;AAChB,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,UAAU,GAAG,IAAI,CAE7D;AAED,gBAAgB;AAChB,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC"}
1
+ {"version":3,"file":"platform-io.d.ts","sourceRoot":"","sources":["../../../src/runtime/platform-io.ts"],"names":[],"mappings":"AACA,OAAO,EAAiB,KAAK,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAEvE,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC5C,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9C,OAAO,CACL,IAAI,EAAE,MAAM,GACX,cAAc,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAC3E,WAAW,CAAC,EAAE,CACZ,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,KACf,OAAO,CAAC,UAAU,CAAC,CAAC;CAC1B,CAAC;AA0LF;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,kBAAkB,GAAG,UAAU,CAgBvE;AAED,wBAAgB,aAAa,IAAI,UAAU,CAM1C;AAED,gBAAgB;AAChB,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,UAAU,GAAG,IAAI,CAE7D;AAED,gBAAgB;AAChB,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC"}
@@ -152,27 +152,26 @@ function createBunIO() {
152
152
  }
153
153
  };
154
154
  }
155
- function getPlatformIO() {
156
- if (platformIO) return platformIO;
157
- const runtime = detectRuntime();
158
- switch (runtime.environment) {
155
+ function createPlatformIOFor(env) {
156
+ switch (env) {
159
157
  case "deno-wasi":
160
- platformIO = createDenoIO();
161
- break;
158
+ return createDenoIO();
162
159
  case "bun-wasi":
163
- platformIO = createBunIO();
164
- break;
160
+ return createBunIO();
165
161
  case "node-wasi":
166
162
  case "node-emscripten":
167
- platformIO = createNodeIO();
168
- break;
163
+ return createNodeIO();
169
164
  default:
170
165
  throw new EnvironmentError(
171
- runtime.environment,
166
+ env,
172
167
  "does not support filesystem operations",
173
168
  "filesystem access"
174
169
  );
175
170
  }
171
+ }
172
+ function getPlatformIO() {
173
+ if (platformIO) return platformIO;
174
+ platformIO = createPlatformIOFor(detectRuntime().environment);
176
175
  return platformIO;
177
176
  }
178
177
  function _setPlatformIOForTesting(io) {
@@ -184,5 +183,6 @@ function _resetPlatformIO() {
184
183
  export {
185
184
  _resetPlatformIO,
186
185
  _setPlatformIOForTesting,
186
+ createPlatformIOFor,
187
187
  getPlatformIO
188
188
  };
@@ -1,6 +1,6 @@
1
1
  import { type RuntimeDetectionResult } from "../detector.js";
2
2
  import type { UnifiedLoaderOptions } from "./types.js";
3
3
  export declare function selectWasmType(runtime: RuntimeDetectionResult, options: UnifiedLoaderOptions): "wasi" | "emscripten";
4
- export declare function isWasiAvailable(): boolean;
5
- export declare function getRecommendedConfig(): UnifiedLoaderOptions;
4
+ export declare function isWasiAvailable(runtime?: RuntimeDetectionResult): boolean;
5
+ export declare function getRecommendedConfig(runtime?: RuntimeDetectionResult): UnifiedLoaderOptions;
6
6
  //# sourceMappingURL=module-selection.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"module-selection.d.ts","sourceRoot":"","sources":["../../../../src/runtime/unified-loader/module-selection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAC5E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEvD,wBAAgB,cAAc,CAC5B,OAAO,EAAE,sBAAsB,EAC/B,OAAO,EAAE,oBAAoB,GAC5B,MAAM,GAAG,YAAY,CAqBvB;AAED,wBAAgB,eAAe,IAAI,OAAO,CAGzC;AAED,wBAAgB,oBAAoB,IAAI,oBAAoB,CAoB3D"}
1
+ {"version":3,"file":"module-selection.d.ts","sourceRoot":"","sources":["../../../../src/runtime/unified-loader/module-selection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAC5E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEvD,wBAAgB,cAAc,CAC5B,OAAO,EAAE,sBAAsB,EAC/B,OAAO,EAAE,oBAAoB,GAC5B,MAAM,GAAG,YAAY,CAqBvB;AAED,wBAAgB,eAAe,CAC7B,OAAO,GAAE,sBAAwC,GAChD,OAAO,CAET;AAED,wBAAgB,oBAAoB,CAClC,OAAO,GAAE,sBAAwC,GAChD,oBAAoB,CAqBtB"}
@@ -14,19 +14,17 @@ function selectWasmType(runtime, options) {
14
14
  }
15
15
  return "emscripten";
16
16
  }
17
- function isWasiAvailable() {
18
- const runtime = detectRuntime();
17
+ function isWasiAvailable(runtime = detectRuntime()) {
19
18
  return runtime.wasmType === "wasi" && runtime.supportsFilesystem;
20
19
  }
21
- function getRecommendedConfig() {
22
- const runtime = detectRuntime();
20
+ function getRecommendedConfig(runtime = detectRuntime()) {
23
21
  if (runtime.environment === "browser") {
24
22
  return {
25
23
  forceWasmType: "emscripten",
26
24
  disableOptimizations: false
27
25
  };
28
26
  }
29
- if (runtime.supportsFilesystem) {
27
+ if (runtime.wasmType === "wasi" && runtime.supportsFilesystem) {
30
28
  return {
31
29
  forceWasmType: "wasi",
32
30
  disableOptimizations: false
@@ -4,7 +4,7 @@
4
4
  * Adapts a WASI module interface to the TagLibModule interface,
5
5
  * providing Emscripten-compatible memory access and string operations.
6
6
  */
7
- import type { FileHandle, TagLibModule } from "../../wasm.js";
7
+ import type { FileHandle, TagLibModule, WasmFileHandle } from "../../wasm.js";
8
8
  import type { WasiModule } from "../wasmer-sdk-loader/types.js";
9
9
  export declare class WasiToTagLibAdapter implements TagLibModule {
10
10
  private readonly wasi;
@@ -27,6 +27,18 @@ export declare class WasiToTagLibAdapter implements TagLibModule {
27
27
  stringToUTF8(str: string, ptr: number, maxBytes: number): number;
28
28
  lengthBytesUTF8(str: string): number;
29
29
  createFileHandle(): FileHandle;
30
+ /**
31
+ * The WASI host module this adapter wraps. Path mode's content gate
32
+ * (taglib-j9ld) needs the host's own detector and its WASI→host path
33
+ * resolution, neither of which belongs on the shared `TagLibModule` surface
34
+ * every backend implements.
35
+ */
36
+ get hostModule(): WasiModule;
37
+ /**
38
+ * The gated path open: `WasiFileHandle.loadFromPath` plus the content check a
39
+ * path needs where a buffer would be refused outright (see `path-open.ts`).
40
+ */
41
+ loadAudioPath(wasiPath: string, displayPath: string): Promise<WasmFileHandle>;
30
42
  version(): string;
31
43
  addFunction(_func: any): number;
32
44
  removeFunction(_ptr: number): void;
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../../src/runtime/wasi-adapter/adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAKhE,qBAAa,mBAAoB,YAAW,YAAY;IACtD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;IAClC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;gBAEtB,UAAU,EAAE,UAAU;IAKlC,UAAU,EAMM,UAAU,UAAU,CAAC;IAErC,IAAI,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAEzB;IAED,IAAI,KAAK,IAAI,SAAS,CAErB;IAED,IAAI,MAAM,IAAI,UAAU,CAEvB;IAED,IAAI,MAAM,IAAI,UAAU,CAEvB;IAED,IAAI,MAAM,IAAI,UAAU,CAEvB;IAED,IAAI,OAAO,IAAI,WAAW,CAEzB;IAED,IAAI,OAAO,IAAI,WAAW,CAEzB;IAED,IAAI,OAAO,IAAI,YAAY,CAE1B;IAED,IAAI,OAAO,IAAI,YAAY,CAE1B;IAED,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAI7B,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIxB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM;IAe9C,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAOjC,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM;IAQhE,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAIpC,gBAAgB,IAAI,UAAU;IAI9B,OAAO,IAAI,MAAM;IAIjB,WAAW,CAAC,KAAK,EAAE,GAAG,GAAG,MAAM;IAM/B,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAMlC,KAAK,CACH,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,SAAS,EAAE,MAAM,EAAE,GAClB,GAAG;IAMN,KAAK,CACH,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,SAAS,EAAE,MAAM,EAAE,EACnB,KAAK,EAAE,GAAG,EAAE,GACX,GAAG;CAKP"}
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../../src/runtime/wasi-adapter/adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC9E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAMhE,qBAAa,mBAAoB,YAAW,YAAY;IACtD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;IAClC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;gBAEtB,UAAU,EAAE,UAAU;IAKlC,UAAU,EAMM,UAAU,UAAU,CAAC;IAErC,IAAI,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAEzB;IAED,IAAI,KAAK,IAAI,SAAS,CAErB;IAED,IAAI,MAAM,IAAI,UAAU,CAEvB;IAED,IAAI,MAAM,IAAI,UAAU,CAEvB;IAED,IAAI,MAAM,IAAI,UAAU,CAEvB;IAED,IAAI,OAAO,IAAI,WAAW,CAEzB;IAED,IAAI,OAAO,IAAI,WAAW,CAEzB;IAED,IAAI,OAAO,IAAI,YAAY,CAE1B;IAED,IAAI,OAAO,IAAI,YAAY,CAE1B;IAED,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAI7B,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIxB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM;IAe9C,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAOjC,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM;IAQhE,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAIpC,gBAAgB,IAAI,UAAU;IAI9B;;;;;OAKG;IACH,IAAI,UAAU,IAAI,UAAU,CAE3B;IAED;;;OAGG;IACH,aAAa,CACX,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,cAAc,CAAC;IAI1B,OAAO,IAAI,MAAM;IAIjB,WAAW,CAAC,KAAK,EAAE,GAAG,GAAG,MAAM;IAM/B,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAMlC,KAAK,CACH,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,SAAS,EAAE,MAAM,EAAE,GAClB,GAAG;IAMN,KAAK,CACH,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,SAAS,EAAE,MAAM,EAAE,EACnB,KAAK,EAAE,GAAG,EAAE,GACX,GAAG;CAKP"}
@@ -4,6 +4,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
4
4
  import { WasmerExecutionError } from "../wasmer-sdk-loader/types.js";
5
5
  import { MemoryError } from "../../errors/classes.js";
6
6
  import { WasiFileHandle } from "./file-handle.js";
7
+ import { openAudioPath } from "./path-open.js";
7
8
  class WasiToTagLibAdapter {
8
9
  constructor(wasiModule) {
9
10
  __publicField(this, "wasi");
@@ -84,6 +85,22 @@ class WasiToTagLibAdapter {
84
85
  createFileHandle() {
85
86
  return new WasiFileHandle(this.wasi);
86
87
  }
88
+ /**
89
+ * The WASI host module this adapter wraps. Path mode's content gate
90
+ * (taglib-j9ld) needs the host's own detector and its WASI→host path
91
+ * resolution, neither of which belongs on the shared `TagLibModule` surface
92
+ * every backend implements.
93
+ */
94
+ get hostModule() {
95
+ return this.wasi;
96
+ }
97
+ /**
98
+ * The gated path open: `WasiFileHandle.loadFromPath` plus the content check a
99
+ * path needs where a buffer would be refused outright (see `path-open.ts`).
100
+ */
101
+ loadAudioPath(wasiPath, displayPath) {
102
+ return openAudioPath(this, wasiPath, displayPath);
103
+ }
87
104
  version() {
88
105
  return this.wasi.tl_version();
89
106
  }
@@ -8,7 +8,10 @@
8
8
  import type { AudioProperties } from "../../types.js";
9
9
  /** The audio-properties block of the C++ snapshot, null when absent. */
10
10
  export declare function getAudioProperties(tagData: Record<string, unknown> | null): AudioProperties | null;
11
- /** OGG codec sniffing: "OpusHead" in the first page payload, else OGG. */
11
+ /**
12
+ * OGG codec sniffing from the first page payload: "OpusHead" (Opus),
13
+ * 0x7F"FLAC" (FLAC-in-Ogg), "Speex " (Speex), else Ogg Vorbis ("OGG").
14
+ */
12
15
  export declare function detectOggCodec(fileData: Uint8Array): string;
13
16
  /**
14
17
  * Format detection: container-based first (works for path and buffer modes),
@@ -1 +1 @@
1
- {"version":3,"file":"audio-properties.d.ts","sourceRoot":"","sources":["../../../../src/runtime/wasi-adapter/audio-properties.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAEV,eAAe,EAEhB,MAAM,gBAAgB,CAAC;AAexB,wEAAwE;AACxE,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GACtC,eAAe,GAAG,IAAI,CA4BxB;AAED,0EAA0E;AAC1E,wBAAgB,cAAc,CAAC,QAAQ,EAAE,UAAU,GAAG,MAAM,CAe3D;AAED;;;GAGG;AACH,wBAAgB,SAAS,CACvB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,EACvC,QAAQ,EAAE,UAAU,GAAG,IAAI,GAC1B,MAAM,CAuDR;AAED,4EAA4E;AAC5E,wBAAgB,KAAK,CACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,EACvC,QAAQ,EAAE,UAAU,GAAG,IAAI,GAC1B,OAAO,CAYT"}
1
+ {"version":3,"file":"audio-properties.d.ts","sourceRoot":"","sources":["../../../../src/runtime/wasi-adapter/audio-properties.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAEV,eAAe,EAEhB,MAAM,gBAAgB,CAAC;AA6CxB,wEAAwE;AACxE,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GACtC,eAAe,GAAG,IAAI,CA4BxB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,UAAU,GAAG,MAAM,CAsB3D;AAED;;;GAGG;AACH,wBAAgB,SAAS,CACvB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,EACvC,QAAQ,EAAE,UAAU,GAAG,IAAI,GAC1B,MAAM,CAyDR;AAED,4EAA4E;AAC5E,wBAAgB,KAAK,CACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,EACvC,QAAQ,EAAE,UAAU,GAAG,IAAI,GAC1B,OAAO,CAYT"}
@@ -1,15 +1,30 @@
1
1
  const CONTAINER_TO_FORMAT = {
2
2
  MP3: "MP3",
3
+ ADTS: "AAC",
3
4
  MP4: "MP4",
4
5
  FLAC: "FLAC",
5
6
  OGG: "OGG",
6
7
  WAV: "WAV",
7
8
  AIFF: "AIFF",
9
+ ASF: "ASF",
10
+ APE: "APE",
11
+ DSF: "DSF",
12
+ DSDIFF: "DSDIFF",
8
13
  WavPack: "WV",
14
+ MPC: "MPC",
9
15
  TTA: "TTA",
10
- ASF: "ASF",
16
+ Shorten: "SHN",
17
+ MOD: "MOD",
18
+ S3M: "S3M",
19
+ IT: "IT",
20
+ XM: "XM",
11
21
  Matroska: "MATROSKA"
12
22
  };
23
+ const OGG_CODEC_TO_FORMAT = {
24
+ Opus: "OPUS",
25
+ FLAC: "OggFLAC",
26
+ Speex: "SPEEX"
27
+ };
13
28
  function getAudioProperties(tagData) {
14
29
  if (!tagData || !("sampleRate" in tagData)) return null;
15
30
  const d = tagData;
@@ -38,17 +53,20 @@ function detectOggCodec(fileData) {
38
53
  if (segCount === void 0) return "OGG";
39
54
  const payloadStart = 27 + segCount;
40
55
  if (fileData.length < payloadStart + 8) return "OGG";
41
- const sig = String.fromCharCode(
42
- ...fileData.slice(payloadStart, payloadStart + 8)
43
- );
44
- if (sig === "OpusHead") return "OPUS";
56
+ const sig = fileData.slice(payloadStart, payloadStart + 8);
57
+ const text = String.fromCharCode(...sig);
58
+ if (text === "OpusHead") return "OPUS";
59
+ if (sig[0] === 127 && sig[1] === 70 && sig[2] === 76 && sig[3] === 65 && sig[4] === 67) return "OggFLAC";
60
+ if (text === "Speex ") return "SPEEX";
45
61
  return "OGG";
46
62
  }
47
63
  function getFormat(tagData, fileData) {
48
64
  const container = tagData?.containerFormat;
49
65
  if (container) {
50
66
  const codec = tagData?.codec;
51
- if (container === "OGG" && codec === "Opus") return "OPUS";
67
+ if (container === "OGG" && codec && OGG_CODEC_TO_FORMAT[codec]) {
68
+ return OGG_CODEC_TO_FORMAT[codec];
69
+ }
52
70
  if (CONTAINER_TO_FORMAT[container]) return CONTAINER_TO_FORMAT[container];
53
71
  }
54
72
  if (!fileData || fileData.length < 8) return "unknown";
@@ -0,0 +1,68 @@
1
+ /**
2
+ * The gated path open for the WASI backend: `WasiFileHandle.loadFromPath` plus
3
+ * the content check a path needs and a buffer does not.
4
+ *
5
+ * `read_from_path` resolves the file class by *extension* first, and upstream's
6
+ * `MPEG::File` reports itself valid for any bytes at all (its `read()` never
7
+ * clears validity, `lib/taglib/taglib/mpeg/mpegfile.cpp`), so `junk.mp3` opens
8
+ * where the same bytes in a buffer are refused. Two independent signals say
9
+ * whether anything was really there, in cost order:
10
+ *
11
+ * 1. {@link statesAudioProperties} — whether the parse read an audio property
12
+ * out of the file. No extra I/O: the snapshot is what the open already
13
+ * produced. A file that states a sample rate is audio TagLib read, whatever
14
+ * its head looks like — which is how an MP3 behind a 4 KiB or 70 KiB APEv2
15
+ * tag (this repo's own corpus shapes, tests/media-checksum-corpus.test.ts)
16
+ * stays readable even though neither detector can see the frames behind the
17
+ * tag.
18
+ * 2. {@link hasRecognizableHead} — whether the head is content the boundary's
19
+ * detector knows, or opens as a buffer. This is what saves a file whose
20
+ * properties are legitimately absent (`lib/taglib/tests/data/segfault.wav`
21
+ * is 30 bytes of `RIFF`/`WAVE`; `tests/test-files/mp4/synth-multi-mdat.mp4`
22
+ * has `ftyp` and no `moov`) and every tag-only file, whose head *is* its tag:
23
+ * content is recognizable even when there is nothing to measure.
24
+ *
25
+ * A path is refused only when *both* say nothing — a zero-length file, junk
26
+ * bytes behind an audio extension. That is the shape of every refusal in this
27
+ * repo's and upstream's corpora (163 fixtures, swept by
28
+ * `tests/checksum-input-contract.test.ts`), and neither signal can refuse a file
29
+ * the buffer form accepts: every detector rule is head-based (MOD's signature at
30
+ * offset 1080 is the deepest, and the window clears it), the ID3v2 rule answers
31
+ * "MP3" rather than giving up when the tag runs past the window
32
+ * (`src/capi/taglib_boundary.c`, `tl_detect_format`), and a head that opens as a
33
+ * buffer *is* the buffer form's own verdict.
34
+ *
35
+ * The one asymmetry that survives is upstream's deliberately corrupt fixtures
36
+ * whose bytes still yield a property (`garbage.mp3`, `sv4_header.mpc`,
37
+ * `sv5_header.mpc`, `stripped.xm`): TagLib reads a header out of them, so the
38
+ * path form keeps accepting them exactly as it did before this change, while the
39
+ * buffer form's narrower magic rules refuse them. Nothing in the C detector can
40
+ * place SV4/SV5 MPC or junk-with-a-frame-header — see taglib-uat8 for that
41
+ * reachability gap — and refusing them here would mean refusing files the parse
42
+ * did read.
43
+ */
44
+ import type { FileHandle, WasmFileHandle } from "../../wasm.js";
45
+ import type { WasiModule } from "../wasmer-sdk-loader/types.js";
46
+ /** The WASI backend this open runs on: its host module (where the detector and
47
+ * the WASI→host path resolution live, `WasiToTagLibAdapter.hostModule`) and its
48
+ * handle factory. */
49
+ export interface PathOpenHost {
50
+ readonly hostModule: WasiModule;
51
+ createFileHandle(): FileHandle;
52
+ }
53
+ /**
54
+ * Load an audio file by path, verifying that its content is audio.
55
+ *
56
+ * Every failure the caller can act on is distinct: `FileOperationError` for a
57
+ * path the host does not have (what the buffer form's own stat answers, so a
58
+ * typo reads the same on both backends), `InvalidFormatError` for a zero-byte
59
+ * file (see below) and for content the boundary could not resolve as audio, and
60
+ * the wasm-level errors unchanged. Either content signal above suffices; both
61
+ * saying nothing is a refusal.
62
+ *
63
+ * The returned handle is the library-owned one (the WASI brand asserted here,
64
+ * the WASI equivalent of `wrapEmbindHandle`), destroyed on any failure — the
65
+ * caller's `AudioFile` takes it over on success.
66
+ */
67
+ export declare function openAudioPath(backend: PathOpenHost, wasiPath: string, displayPath: string): Promise<WasmFileHandle>;
68
+ //# sourceMappingURL=path-open.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-open.d.ts","sourceRoot":"","sources":["../../../../src/runtime/wasi-adapter/path-open.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAqBhE;;qBAEqB;AACrB,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,gBAAgB,IAAI,UAAU,CAAC;CAChC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,YAAY,EACrB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,cAAc,CAAC,CA0CzB"}