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.
- package/LICENSE +1 -1
- package/README.md +197 -16
- package/dist/index.browser.d.ts +24 -4
- package/dist/index.browser.d.ts.map +1 -1
- package/dist/index.browser.js +1139 -217
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/simple.browser.js +539 -209
- package/dist/src/constants/properties.d.ts +2 -2
- package/dist/src/constants/specialized-properties.d.ts +2 -2
- package/dist/src/constants/specialized-properties.js +2 -2
- package/dist/src/errors/base.d.ts +17 -2
- package/dist/src/errors/base.d.ts.map +1 -1
- package/dist/src/errors/base.js +18 -0
- package/dist/src/runtime/detector.d.ts +16 -1
- package/dist/src/runtime/detector.d.ts.map +1 -1
- package/dist/src/runtime/detector.js +58 -52
- package/dist/src/runtime/platform-io.d.ts +8 -0
- package/dist/src/runtime/platform-io.d.ts.map +1 -1
- package/dist/src/runtime/platform-io.js +11 -11
- package/dist/src/runtime/unified-loader/module-selection.d.ts +2 -2
- package/dist/src/runtime/unified-loader/module-selection.d.ts.map +1 -1
- package/dist/src/runtime/unified-loader/module-selection.js +3 -5
- package/dist/src/runtime/wasi-adapter/adapter.d.ts +13 -1
- package/dist/src/runtime/wasi-adapter/adapter.d.ts.map +1 -1
- package/dist/src/runtime/wasi-adapter/adapter.js +17 -0
- package/dist/src/runtime/wasi-adapter/audio-properties.d.ts +4 -1
- package/dist/src/runtime/wasi-adapter/audio-properties.d.ts.map +1 -1
- package/dist/src/runtime/wasi-adapter/audio-properties.js +24 -6
- package/dist/src/runtime/wasi-adapter/path-open.d.ts +68 -0
- package/dist/src/runtime/wasi-adapter/path-open.d.ts.map +1 -0
- package/dist/src/runtime/wasi-adapter/path-open.js +76 -0
- package/dist/src/runtime/wasi-adapter/wasm-io.d.ts.map +1 -1
- package/dist/src/runtime/wasi-adapter/wasm-io.js +36 -28
- package/dist/src/runtime/wasi-host-loader.js +8 -3
- package/dist/src/runtime/wasmer-sdk-loader/types.d.ts +13 -0
- package/dist/src/runtime/wasmer-sdk-loader/types.d.ts.map +1 -1
- package/dist/src/simple/checksum-operations.d.ts +25 -0
- package/dist/src/simple/checksum-operations.d.ts.map +1 -0
- package/dist/src/simple/checksum-operations.js +7 -0
- package/dist/src/simple/index.d.ts +2 -0
- package/dist/src/simple/index.d.ts.map +1 -1
- package/dist/src/simple/index.js +2 -0
- package/dist/src/taglib/audio-file-checksum.d.ts +47 -0
- package/dist/src/taglib/audio-file-checksum.d.ts.map +1 -0
- package/dist/src/taglib/audio-file-checksum.js +77 -0
- package/dist/src/taglib/audio-file-impl.d.ts +4 -0
- package/dist/src/taglib/audio-file-impl.d.ts.map +1 -1
- package/dist/src/taglib/audio-file-impl.js +34 -2
- package/dist/src/taglib/audio-file-interface.d.ts +17 -0
- package/dist/src/taglib/audio-file-interface.d.ts.map +1 -1
- package/dist/src/taglib/embind-adapter.d.ts.map +1 -1
- package/dist/src/taglib/embind-adapter.js +4 -1
- package/dist/src/taglib/id3v2-frames.d.ts.map +1 -1
- package/dist/src/taglib/id3v2-frames.js +2 -2
- package/dist/src/taglib/media-ranges.d.ts +85 -0
- package/dist/src/taglib/media-ranges.d.ts.map +1 -0
- package/dist/src/taglib/media-ranges.js +192 -0
- package/dist/src/taglib/metadata-extent.d.ts +55 -0
- package/dist/src/taglib/metadata-extent.d.ts.map +1 -1
- package/dist/src/taglib/metadata-extent.js +24 -6
- package/dist/src/taglib/taglib-class.d.ts.map +1 -1
- package/dist/src/taglib/taglib-class.js +13 -24
- package/dist/src/types/audio-formats.d.ts +5 -5
- package/dist/src/types/audio-formats.d.ts.map +1 -1
- package/dist/src/types/format-property-keys.d.ts +1 -1
- package/dist/src/types/format-property-keys.d.ts.map +1 -1
- package/dist/src/types/tags.d.ts +8 -1
- package/dist/src/types/tags.d.ts.map +1 -1
- package/dist/src/utils/path.d.ts +12 -0
- package/dist/src/utils/path.d.ts.map +1 -1
- package/dist/src/utils/path.js +19 -0
- package/dist/src/utils/tag-mapping.d.ts.map +1 -1
- package/dist/src/utils/tag-mapping.js +2 -0
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/wasm.d.ts +9 -0
- package/dist/src/wasm.d.ts.map +1 -1
- package/dist/src/web-utils/data-url.d.ts.map +1 -1
- package/dist/src/web-utils/data-url.js +4 -2
- package/dist/taglib-wasi.wasm +0 -0
- package/dist/taglib-web.wasm +0 -0
- package/dist/web.browser.d.ts +13 -0
- package/dist/web.browser.d.ts.map +1 -0
- package/dist/web.browser.js +3630 -0
- 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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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"}
|
package/dist/src/errors/base.js
CHANGED
|
@@ -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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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":"
|
|
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
|
|
156
|
-
|
|
157
|
-
const runtime = detectRuntime();
|
|
158
|
-
switch (runtime.environment) {
|
|
155
|
+
function createPlatformIOFor(env) {
|
|
156
|
+
switch (env) {
|
|
159
157
|
case "deno-wasi":
|
|
160
|
-
|
|
161
|
-
break;
|
|
158
|
+
return createDenoIO();
|
|
162
159
|
case "bun-wasi":
|
|
163
|
-
|
|
164
|
-
break;
|
|
160
|
+
return createBunIO();
|
|
165
161
|
case "node-wasi":
|
|
166
162
|
case "node-emscripten":
|
|
167
|
-
|
|
168
|
-
break;
|
|
163
|
+
return createNodeIO();
|
|
169
164
|
default:
|
|
170
165
|
throw new EnvironmentError(
|
|
171
|
-
|
|
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,
|
|
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;
|
|
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
|
-
/**
|
|
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;
|
|
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
|
-
|
|
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 =
|
|
42
|
-
|
|
43
|
-
);
|
|
44
|
-
if (sig ===
|
|
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
|
|
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"}
|