@zntc/wasm 0.1.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 +21 -0
- package/README.md +72 -0
- package/dist/index.js +493 -0
- package/dist/shared/compat-engines.d.ts +30 -0
- package/dist/shared/index.d.ts +185 -0
- package/dist/wasm/index.d.ts +63 -0
- package/package.json +59 -0
- package/zntc-bundler.wasm +0 -0
- package/zntc.wasm +0 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ohah
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# @zntc/wasm
|
|
2
|
+
|
|
3
|
+
ZNTC 의 WASM 빌드 — 브라우저 / Bun / Node 환경에서 native binary (`zntc.node`) 없이 순수 WASM 으로 트랜스파일/번들 실행.
|
|
4
|
+
|
|
5
|
+
`@zntc/core` 의 NAPI 모듈을 쓸 수 없는 환경 (Edge runtime, Cloudflare Workers, 브라우저 in-page transpile 등) 용.
|
|
6
|
+
|
|
7
|
+
## 설치
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
bun add -D @zntc/wasm
|
|
11
|
+
# 또는
|
|
12
|
+
npm i -D @zntc/wasm
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
WASM binary (`zntc.wasm` ~1.1MB / `zntc-bundler.wasm` ~2.0MB, gzipped 시 388KB / 675KB) 가 함께 install 됨.
|
|
16
|
+
|
|
17
|
+
## 사용 예
|
|
18
|
+
|
|
19
|
+
### Browser / Edge runtime
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import { init, transpile } from '@zntc/wasm';
|
|
23
|
+
import wasmUrl from '@zntc/wasm/zntc.wasm?url'; // Vite 전용 syntax
|
|
24
|
+
|
|
25
|
+
await init(wasmUrl);
|
|
26
|
+
const r = transpile('const x: number = 1;', { filename: 'input.ts' });
|
|
27
|
+
console.log(r.code);
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
> Vite 가 아닌 bundler 는 `fetch(new URL('@zntc/wasm/zntc.wasm', import.meta.url))` 또는 각자의 asset import 패턴 사용.
|
|
31
|
+
|
|
32
|
+
### Node.js / Bun (auto-resolve)
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
import { init, transpile } from '@zntc/wasm';
|
|
36
|
+
|
|
37
|
+
await init(); // 동봉 zntc.wasm 자동 로드 (fs.readFileSync)
|
|
38
|
+
const r = transpile('const x: number = 1;', { filename: 'input.ts' });
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Bundler 사용
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import { bundlerLastErrorMessage, build, initBundler } from '@zntc/wasm';
|
|
45
|
+
import wasmUrl from '@zntc/wasm/zntc-bundler.wasm?url';
|
|
46
|
+
|
|
47
|
+
await initBundler(wasmUrl); // transpile 용 init() 와 별도
|
|
48
|
+
const out = build('/main.ts', { format: 'esm', target: 'es2020' });
|
|
49
|
+
if (out === null) throw new Error(bundlerLastErrorMessage());
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
`build` 는 sync 이며 실패 시 `null` 반환 — `bundlerLastErrorMessage()` 로 마지막 에러 조회.
|
|
53
|
+
|
|
54
|
+
## NAPI 와 차이
|
|
55
|
+
|
|
56
|
+
| 항목 | @zntc/core (NAPI) | @zntc/wasm |
|
|
57
|
+
| ----------- | ----------------- | ------------------------------------- |
|
|
58
|
+
| 환경 | Node.js / Bun | + Browser / Edge / Workers |
|
|
59
|
+
| 속도 | 빠름 (~native) | 50~70% (WASM 오버헤드) |
|
|
60
|
+
| binary 크기 | ~4MB (.node) | 1.1MB + 2.0MB (gzipped 388KB + 675KB) |
|
|
61
|
+
| install | 플랫폼별 prebuilt | 단일 wasm (universal) |
|
|
62
|
+
|
|
63
|
+
대부분의 server-side 빌드 사용 사례는 `@zntc/core` 권장. `@zntc/wasm` 은 환경 제약 시.
|
|
64
|
+
|
|
65
|
+
## 관련
|
|
66
|
+
|
|
67
|
+
- [@zntc/core](https://npmjs.com/package/@zntc/core) — Native (NAPI) 빌드
|
|
68
|
+
- [docs/USAGE.md](https://github.com/ohah/zts/blob/main/docs/USAGE.md)
|
|
69
|
+
|
|
70
|
+
## 라이센스
|
|
71
|
+
|
|
72
|
+
MIT.
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined")
|
|
5
|
+
return require.apply(this, arguments);
|
|
6
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
7
|
+
});
|
|
8
|
+
// ../shared/index.ts
|
|
9
|
+
var ES_TARGET_BITS = {
|
|
10
|
+
es5: 268435455,
|
|
11
|
+
es2015: 117438464,
|
|
12
|
+
es2016: 117436416,
|
|
13
|
+
es2017: 117432320,
|
|
14
|
+
es2018: 16760832,
|
|
15
|
+
es2019: 16744448,
|
|
16
|
+
es2020: 16646144,
|
|
17
|
+
es2021: 16515072,
|
|
18
|
+
es2022: 12582912,
|
|
19
|
+
es2023: 8388608,
|
|
20
|
+
es2024: 8388608,
|
|
21
|
+
es2025: 0,
|
|
22
|
+
esnext: 0
|
|
23
|
+
};
|
|
24
|
+
function targetToUnsupported(target) {
|
|
25
|
+
if (!target)
|
|
26
|
+
return 0;
|
|
27
|
+
return ES_TARGET_BITS[target] ?? 0;
|
|
28
|
+
}
|
|
29
|
+
function buildOptionsJson(opts = {}, unsupportedOverride) {
|
|
30
|
+
const payload = {};
|
|
31
|
+
if (opts.target)
|
|
32
|
+
payload.target = opts.target;
|
|
33
|
+
if (unsupportedOverride !== undefined && unsupportedOverride !== 0)
|
|
34
|
+
payload.unsupported = unsupportedOverride;
|
|
35
|
+
if (opts.flow)
|
|
36
|
+
payload.flow = true;
|
|
37
|
+
if (opts.jsxInJs)
|
|
38
|
+
payload.jsxInJs = true;
|
|
39
|
+
if (opts.reactRefresh)
|
|
40
|
+
payload.reactRefresh = true;
|
|
41
|
+
if (opts.reactRefreshHookSignatures)
|
|
42
|
+
payload.reactRefreshHookSignatures = true;
|
|
43
|
+
if (opts.jsx !== undefined) {
|
|
44
|
+
payload.jsx = opts.jsx === "automatic-dev" ? "automatic_dev" : opts.jsx;
|
|
45
|
+
}
|
|
46
|
+
if (opts.jsxFactory)
|
|
47
|
+
payload.jsxFactory = opts.jsxFactory;
|
|
48
|
+
if (opts.jsxFragment)
|
|
49
|
+
payload.jsxFragment = opts.jsxFragment;
|
|
50
|
+
if (opts.jsxImportSource)
|
|
51
|
+
payload.jsxImportSource = opts.jsxImportSource;
|
|
52
|
+
if (opts.dropConsole)
|
|
53
|
+
payload.dropConsole = true;
|
|
54
|
+
if (opts.dropDebugger)
|
|
55
|
+
payload.dropDebugger = true;
|
|
56
|
+
if (opts.asciiOnly)
|
|
57
|
+
payload.asciiOnly = true;
|
|
58
|
+
if (opts.charsetUtf8)
|
|
59
|
+
payload.charsetUtf8 = true;
|
|
60
|
+
if (opts.experimentalDecorators)
|
|
61
|
+
payload.experimentalDecorators = true;
|
|
62
|
+
if (opts.emitDecoratorMetadata)
|
|
63
|
+
payload.emitDecoratorMetadata = true;
|
|
64
|
+
if (opts.useDefineForClassFields === false)
|
|
65
|
+
payload.useDefineForClassFields = false;
|
|
66
|
+
if (opts.verbatimModuleSyntax !== undefined)
|
|
67
|
+
payload.verbatimModuleSyntax = opts.verbatimModuleSyntax;
|
|
68
|
+
if (opts.tsconfigPath)
|
|
69
|
+
payload.tsconfigPath = opts.tsconfigPath;
|
|
70
|
+
if (opts.tsconfigRaw)
|
|
71
|
+
payload.tsconfigRaw = opts.tsconfigRaw;
|
|
72
|
+
if (opts.format)
|
|
73
|
+
payload.format = opts.format;
|
|
74
|
+
if (opts.quotes)
|
|
75
|
+
payload.quotes = opts.quotes;
|
|
76
|
+
if (opts.platform === "react-native")
|
|
77
|
+
payload.platform = "react_native";
|
|
78
|
+
else if (opts.platform)
|
|
79
|
+
payload.platform = opts.platform;
|
|
80
|
+
if (opts.minifyWhitespace || opts.minify)
|
|
81
|
+
payload.minifyWhitespace = true;
|
|
82
|
+
if (opts.minifyIdentifiers || opts.minify)
|
|
83
|
+
payload.minifyIdentifiers = true;
|
|
84
|
+
if (opts.minifySyntax || opts.minify)
|
|
85
|
+
payload.minifySyntax = true;
|
|
86
|
+
if (opts.sourcemap)
|
|
87
|
+
payload.sourcemap = true;
|
|
88
|
+
if (opts.sourcemapDebugIds)
|
|
89
|
+
payload.sourcemapDebugIds = true;
|
|
90
|
+
if (opts.sourcesContent === false)
|
|
91
|
+
payload.sourcesContent = false;
|
|
92
|
+
if (opts.sourceRoot)
|
|
93
|
+
payload.sourceRoot = opts.sourceRoot;
|
|
94
|
+
if (opts.define && opts.define.length > 0)
|
|
95
|
+
payload.define = opts.define;
|
|
96
|
+
if (opts.stopAfter)
|
|
97
|
+
payload.stopAfter = opts.stopAfter;
|
|
98
|
+
return JSON.stringify(payload);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// index.ts
|
|
102
|
+
var wasm = null;
|
|
103
|
+
var encoder = new TextEncoder;
|
|
104
|
+
var decoder = new TextDecoder;
|
|
105
|
+
function createWasiImports(memory) {
|
|
106
|
+
const ok = () => 0;
|
|
107
|
+
return {
|
|
108
|
+
wasi_snapshot_preview1: {
|
|
109
|
+
fd_write(fd, iovs_ptr, iovs_len, nwritten_ptr) {
|
|
110
|
+
const mem = new DataView(memory().buffer);
|
|
111
|
+
const bytes = new Uint8Array(memory().buffer);
|
|
112
|
+
let written = 0;
|
|
113
|
+
for (let i = 0;i < iovs_len; i++) {
|
|
114
|
+
const ptr = mem.getUint32(iovs_ptr + i * 8, true);
|
|
115
|
+
const len = mem.getUint32(iovs_ptr + i * 8 + 4, true);
|
|
116
|
+
const chunk = bytes.slice(ptr, ptr + len);
|
|
117
|
+
if (fd === 2)
|
|
118
|
+
console.error(decoder.decode(chunk));
|
|
119
|
+
written += len;
|
|
120
|
+
}
|
|
121
|
+
mem.setUint32(nwritten_ptr, written, true);
|
|
122
|
+
return 0;
|
|
123
|
+
},
|
|
124
|
+
fd_read: ok,
|
|
125
|
+
fd_seek: ok,
|
|
126
|
+
fd_pwrite: ok,
|
|
127
|
+
fd_pread: ok,
|
|
128
|
+
fd_close: ok,
|
|
129
|
+
fd_fdstat_get: ok,
|
|
130
|
+
fd_fdstat_set_flags: ok,
|
|
131
|
+
fd_filestat_get: ok,
|
|
132
|
+
fd_prestat_get: () => 8,
|
|
133
|
+
fd_prestat_dir_name: ok,
|
|
134
|
+
fd_sync: ok,
|
|
135
|
+
random_get(buf_ptr, buf_len) {
|
|
136
|
+
const bytes = new Uint8Array(memory().buffer, buf_ptr, buf_len);
|
|
137
|
+
if (typeof globalThis.crypto !== "undefined") {
|
|
138
|
+
crypto.getRandomValues(bytes);
|
|
139
|
+
} else {
|
|
140
|
+
for (let i = 0;i < buf_len; i++)
|
|
141
|
+
bytes[i] = Math.random() * 256 | 0;
|
|
142
|
+
}
|
|
143
|
+
return 0;
|
|
144
|
+
},
|
|
145
|
+
clock_time_get(clock_id, _precision, ts_ptr) {
|
|
146
|
+
const mem = new DataView(memory().buffer);
|
|
147
|
+
const ns = clock_id === 0 ? BigInt(Date.now()) * 1000000n : BigInt(Math.floor(performance.now() * 1e6));
|
|
148
|
+
mem.setBigUint64(ts_ptr, ns, true);
|
|
149
|
+
return 0;
|
|
150
|
+
},
|
|
151
|
+
clock_res_get(_clock_id, ts_ptr) {
|
|
152
|
+
const mem = new DataView(memory().buffer);
|
|
153
|
+
mem.setBigUint64(ts_ptr, 1000000n, true);
|
|
154
|
+
return 0;
|
|
155
|
+
},
|
|
156
|
+
args_sizes_get(argc_ptr, argv_buf_size_ptr) {
|
|
157
|
+
const mem = new DataView(memory().buffer);
|
|
158
|
+
mem.setUint32(argc_ptr, 0, true);
|
|
159
|
+
mem.setUint32(argv_buf_size_ptr, 0, true);
|
|
160
|
+
return 0;
|
|
161
|
+
},
|
|
162
|
+
args_get: ok,
|
|
163
|
+
environ_sizes_get(envc_ptr, env_buf_size_ptr) {
|
|
164
|
+
const mem = new DataView(memory().buffer);
|
|
165
|
+
mem.setUint32(envc_ptr, 0, true);
|
|
166
|
+
mem.setUint32(env_buf_size_ptr, 0, true);
|
|
167
|
+
return 0;
|
|
168
|
+
},
|
|
169
|
+
environ_get: ok,
|
|
170
|
+
proc_exit(code) {
|
|
171
|
+
throw new Error(`zntc-wasm: proc_exit(${code})`);
|
|
172
|
+
},
|
|
173
|
+
sched_yield: ok,
|
|
174
|
+
poll_oneoff: ok,
|
|
175
|
+
path_open: () => 8,
|
|
176
|
+
path_filestat_get: () => 8,
|
|
177
|
+
path_unlink_file: ok,
|
|
178
|
+
path_create_directory: ok,
|
|
179
|
+
path_remove_directory: ok,
|
|
180
|
+
path_rename: ok,
|
|
181
|
+
path_link: ok,
|
|
182
|
+
path_symlink: ok,
|
|
183
|
+
path_readlink: () => 8
|
|
184
|
+
},
|
|
185
|
+
wasi: {
|
|
186
|
+
"thread-spawn": () => -1
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
function writeString(s) {
|
|
191
|
+
const bytes = encoder.encode(s);
|
|
192
|
+
const ptr = wasm.alloc(bytes.length);
|
|
193
|
+
if (ptr === 0)
|
|
194
|
+
throw new Error("zntc-wasm: alloc failed");
|
|
195
|
+
new Uint8Array(wasm.memory.buffer, ptr, bytes.length).set(bytes);
|
|
196
|
+
return [ptr, bytes.length];
|
|
197
|
+
}
|
|
198
|
+
function readString(ptr, len) {
|
|
199
|
+
return decoder.decode(new Uint8Array(wasm.memory.buffer, ptr, len));
|
|
200
|
+
}
|
|
201
|
+
async function resolveWasmSource(input, defaultFile) {
|
|
202
|
+
if (input === undefined) {
|
|
203
|
+
const fs = await import("node:fs");
|
|
204
|
+
const path = await import("node:path");
|
|
205
|
+
const url = await import("node:url");
|
|
206
|
+
const __dirname2 = path.dirname(url.fileURLToPath(import.meta.url));
|
|
207
|
+
const candidates = [path.join(__dirname2, defaultFile), path.join(__dirname2, "..", defaultFile)];
|
|
208
|
+
for (const candidate of candidates) {
|
|
209
|
+
if (fs.existsSync(candidate))
|
|
210
|
+
return fs.readFileSync(candidate);
|
|
211
|
+
}
|
|
212
|
+
throw new Error(`zntc-wasm: ${defaultFile} not found near ${__dirname2}`);
|
|
213
|
+
}
|
|
214
|
+
if (input instanceof WebAssembly.Module)
|
|
215
|
+
return input;
|
|
216
|
+
if (input instanceof Response)
|
|
217
|
+
return input;
|
|
218
|
+
if (input instanceof ArrayBuffer || ArrayBuffer.isView(input)) {
|
|
219
|
+
return input;
|
|
220
|
+
}
|
|
221
|
+
return await fetch(input);
|
|
222
|
+
}
|
|
223
|
+
async function instantiateWasm(source, imports) {
|
|
224
|
+
if (source instanceof WebAssembly.Module) {
|
|
225
|
+
return new WebAssembly.Instance(source, imports);
|
|
226
|
+
}
|
|
227
|
+
if (source instanceof Response) {
|
|
228
|
+
const result2 = await WebAssembly.instantiateStreaming(source, imports);
|
|
229
|
+
return result2.instance;
|
|
230
|
+
}
|
|
231
|
+
const result = await WebAssembly.instantiate(source, imports);
|
|
232
|
+
return result.instance;
|
|
233
|
+
}
|
|
234
|
+
async function init(input) {
|
|
235
|
+
if (wasm)
|
|
236
|
+
return;
|
|
237
|
+
const source = await resolveWasmSource(input, "zntc.wasm");
|
|
238
|
+
let memory;
|
|
239
|
+
const imports = createWasiImports(() => memory);
|
|
240
|
+
const instance = await instantiateWasm(source, imports);
|
|
241
|
+
memory = instance.exports.memory;
|
|
242
|
+
wasm = instance.exports;
|
|
243
|
+
}
|
|
244
|
+
function initSync(input) {
|
|
245
|
+
if (wasm)
|
|
246
|
+
return;
|
|
247
|
+
let memory;
|
|
248
|
+
const imports = createWasiImports(() => memory);
|
|
249
|
+
const mod = input instanceof WebAssembly.Module ? input : new WebAssembly.Module(input instanceof ArrayBuffer ? input : input.buffer);
|
|
250
|
+
const instance = new WebAssembly.Instance(mod, imports);
|
|
251
|
+
memory = instance.exports.memory;
|
|
252
|
+
wasm = instance.exports;
|
|
253
|
+
}
|
|
254
|
+
function transpile(source, options = {}) {
|
|
255
|
+
if (!wasm) {
|
|
256
|
+
throw new Error("zntc-wasm: not initialized. Call init() or initSync() first.");
|
|
257
|
+
}
|
|
258
|
+
const [srcPtr, srcLen] = writeString(source);
|
|
259
|
+
const [filePtr, fileLen] = options.filename ? writeString(options.filename) : [0, 0];
|
|
260
|
+
const optsJson = buildOptionsJson(options, targetToUnsupported(options.target));
|
|
261
|
+
const [optsPtr, optsLen] = writeString(optsJson);
|
|
262
|
+
try {
|
|
263
|
+
const packed = wasm.transpile(srcPtr, srcLen, filePtr, fileLen, optsPtr, optsLen);
|
|
264
|
+
const outPtr = Number(packed >> 32n);
|
|
265
|
+
const outLen = Number(packed & 0xffffffffn);
|
|
266
|
+
const errLen = wasm.get_error_len();
|
|
267
|
+
const errMsg = errLen === 0 ? "" : readString(wasm.get_error_ptr(), errLen);
|
|
268
|
+
if (outPtr === 0) {
|
|
269
|
+
if (outLen === 0 && errLen === 0)
|
|
270
|
+
return { code: "" };
|
|
271
|
+
throw new Error(`zntc-wasm: ${errMsg || "unknown error"}`);
|
|
272
|
+
}
|
|
273
|
+
const raw = readString(outPtr, outLen);
|
|
274
|
+
wasm.dealloc(outPtr, outLen);
|
|
275
|
+
const nullIdx = options.sourcemap ? raw.indexOf("\x00") : -1;
|
|
276
|
+
const result = nullIdx !== -1 ? { code: raw.slice(0, nullIdx), map: raw.slice(nullIdx + 1) } : { code: raw };
|
|
277
|
+
if (errMsg)
|
|
278
|
+
result.errors = errMsg;
|
|
279
|
+
return result;
|
|
280
|
+
} finally {
|
|
281
|
+
wasm.dealloc(srcPtr, srcLen);
|
|
282
|
+
if (filePtr)
|
|
283
|
+
wasm.dealloc(filePtr, fileLen);
|
|
284
|
+
wasm.dealloc(optsPtr, optsLen);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
class VirtualFileSystem {
|
|
289
|
+
files = new Map;
|
|
290
|
+
set(path, content) {
|
|
291
|
+
const bytes = typeof content === "string" ? encoder.encode(content) : content;
|
|
292
|
+
this.files.set(path, bytes);
|
|
293
|
+
}
|
|
294
|
+
get(path) {
|
|
295
|
+
return this.files.get(path);
|
|
296
|
+
}
|
|
297
|
+
has(path) {
|
|
298
|
+
return this.files.has(path);
|
|
299
|
+
}
|
|
300
|
+
delete(path) {
|
|
301
|
+
return this.files.delete(path);
|
|
302
|
+
}
|
|
303
|
+
paths() {
|
|
304
|
+
return this.files.keys();
|
|
305
|
+
}
|
|
306
|
+
size() {
|
|
307
|
+
return this.files.size;
|
|
308
|
+
}
|
|
309
|
+
clear() {
|
|
310
|
+
this.files.clear();
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
var bundler = null;
|
|
314
|
+
var bundlerMemory = null;
|
|
315
|
+
var bundlerVfs = null;
|
|
316
|
+
function readBundlerString(ptr, len) {
|
|
317
|
+
const view = new Uint8Array(bundlerMemory.buffer, ptr, len);
|
|
318
|
+
return decoder.decode(view.slice());
|
|
319
|
+
}
|
|
320
|
+
function packBytes(data) {
|
|
321
|
+
if (!bundler || !bundlerMemory)
|
|
322
|
+
return 0n;
|
|
323
|
+
const ptr = bundler.alloc(data.length);
|
|
324
|
+
if (ptr === 0)
|
|
325
|
+
return 0n;
|
|
326
|
+
new Uint8Array(bundlerMemory.buffer, ptr, data.length).set(data);
|
|
327
|
+
return BigInt(ptr) << 32n | BigInt(data.length);
|
|
328
|
+
}
|
|
329
|
+
function createBundlerImports(memory) {
|
|
330
|
+
const wasi = createWasiImports(memory);
|
|
331
|
+
return {
|
|
332
|
+
...wasi,
|
|
333
|
+
zntc_fs: {
|
|
334
|
+
readFile(pathPtr, pathLen, _maxBytes) {
|
|
335
|
+
const path = readBundlerString(pathPtr, pathLen);
|
|
336
|
+
const data = bundlerVfs?.get(path);
|
|
337
|
+
if (!data)
|
|
338
|
+
return 0n;
|
|
339
|
+
return packBytes(data);
|
|
340
|
+
},
|
|
341
|
+
statFile(pathPtr, pathLen, outSize, outKind, outMtimeLo, outMtimeHi) {
|
|
342
|
+
const path = readBundlerString(pathPtr, pathLen);
|
|
343
|
+
const data = bundlerVfs?.get(path);
|
|
344
|
+
if (!data)
|
|
345
|
+
return 1;
|
|
346
|
+
const view = new DataView(bundlerMemory.buffer);
|
|
347
|
+
view.setBigUint64(outSize, BigInt(data.length), true);
|
|
348
|
+
new Uint8Array(bundlerMemory.buffer, outKind, 1)[0] = 0;
|
|
349
|
+
view.setBigUint64(outMtimeLo, 0n, true);
|
|
350
|
+
view.setBigUint64(outMtimeHi, 0n, true);
|
|
351
|
+
return 0;
|
|
352
|
+
},
|
|
353
|
+
access(pathPtr, pathLen) {
|
|
354
|
+
const path = readBundlerString(pathPtr, pathLen);
|
|
355
|
+
return bundlerVfs?.has(path) ? 0 : 1;
|
|
356
|
+
},
|
|
357
|
+
realpath(pathPtr, pathLen) {
|
|
358
|
+
const path = readBundlerString(pathPtr, pathLen);
|
|
359
|
+
if (!bundlerVfs?.has(path))
|
|
360
|
+
return 0n;
|
|
361
|
+
return packBytes(encoder.encode(path));
|
|
362
|
+
},
|
|
363
|
+
listDir(_pathPtr, _pathLen) {
|
|
364
|
+
return 0n;
|
|
365
|
+
},
|
|
366
|
+
hostFreeBytes(ptr, len) {
|
|
367
|
+
bundler?.dealloc(ptr, len);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
async function initBundler(vfs, input) {
|
|
373
|
+
if (bundler)
|
|
374
|
+
return;
|
|
375
|
+
const source = await resolveWasmSource(input, "zntc-bundler.wasm");
|
|
376
|
+
const memory = new WebAssembly.Memory({
|
|
377
|
+
initial: 1024,
|
|
378
|
+
maximum: 65536,
|
|
379
|
+
shared: true
|
|
380
|
+
});
|
|
381
|
+
const bundlerImports = createBundlerImports(() => memory);
|
|
382
|
+
const imports = {
|
|
383
|
+
...bundlerImports,
|
|
384
|
+
env: { memory }
|
|
385
|
+
};
|
|
386
|
+
const instance = await instantiateWasm(source, imports);
|
|
387
|
+
bundler = instance.exports;
|
|
388
|
+
bundlerMemory = memory;
|
|
389
|
+
bundlerVfs = vfs;
|
|
390
|
+
}
|
|
391
|
+
function bundlerVersion() {
|
|
392
|
+
if (!bundler) {
|
|
393
|
+
throw new Error("zntc-wasm: bundler not initialized. Call initBundler() first.");
|
|
394
|
+
}
|
|
395
|
+
return bundler.bundler_version();
|
|
396
|
+
}
|
|
397
|
+
function encodeBundleOptions(options) {
|
|
398
|
+
if (!options)
|
|
399
|
+
return { ptr: 0, len: 0 };
|
|
400
|
+
const expanded = { ...options };
|
|
401
|
+
if (expanded.minify) {
|
|
402
|
+
expanded.minifyWhitespace = expanded.minifyWhitespace ?? true;
|
|
403
|
+
expanded.minifyIdentifiers = expanded.minifyIdentifiers ?? true;
|
|
404
|
+
expanded.minifySyntax = expanded.minifySyntax ?? true;
|
|
405
|
+
}
|
|
406
|
+
delete expanded.minify;
|
|
407
|
+
if (expanded.target && expanded.unsupported == null) {
|
|
408
|
+
const bits = targetToUnsupported(expanded.target);
|
|
409
|
+
if (bits !== 0)
|
|
410
|
+
expanded.unsupported = bits;
|
|
411
|
+
}
|
|
412
|
+
delete expanded.target;
|
|
413
|
+
const optsBytes = encoder.encode(JSON.stringify(expanded));
|
|
414
|
+
const ptr = bundler.alloc(optsBytes.length);
|
|
415
|
+
if (ptr === 0)
|
|
416
|
+
throw new Error("zntc-wasm: bundler alloc failed");
|
|
417
|
+
new Uint8Array(bundlerMemory.buffer, ptr, optsBytes.length).set(optsBytes);
|
|
418
|
+
return { ptr, len: optsBytes.length };
|
|
419
|
+
}
|
|
420
|
+
function bundlerLastErrorMessage() {
|
|
421
|
+
if (!bundler || !bundlerMemory)
|
|
422
|
+
return "";
|
|
423
|
+
const packed = bundler.last_error_message_get();
|
|
424
|
+
if (packed === 0n)
|
|
425
|
+
return "";
|
|
426
|
+
const ptr = Number(packed >> 32n);
|
|
427
|
+
const len = Number(packed & 0xffffffffn);
|
|
428
|
+
const view = new Uint8Array(bundlerMemory.buffer, ptr, len);
|
|
429
|
+
return decoder.decode(view.slice());
|
|
430
|
+
}
|
|
431
|
+
function build(entryPath, options) {
|
|
432
|
+
if (!bundler || !bundlerMemory) {
|
|
433
|
+
throw new Error("zntc-wasm: bundler not initialized. Call initBundler() first.");
|
|
434
|
+
}
|
|
435
|
+
const entryBytes = encoder.encode(entryPath);
|
|
436
|
+
const entryPtr = bundler.alloc(entryBytes.length);
|
|
437
|
+
if (entryPtr === 0)
|
|
438
|
+
throw new Error("zntc-wasm: bundler alloc failed");
|
|
439
|
+
new Uint8Array(bundlerMemory.buffer, entryPtr, entryBytes.length).set(entryBytes);
|
|
440
|
+
const { ptr: optsPtr, len: optsLen } = encodeBundleOptions(options);
|
|
441
|
+
try {
|
|
442
|
+
const packed = bundler.build(entryPtr, entryBytes.length, optsPtr, optsLen);
|
|
443
|
+
if (packed === 0n)
|
|
444
|
+
return null;
|
|
445
|
+
const outPtr = Number(packed >> 32n);
|
|
446
|
+
const outLen = Number(packed & 0xffffffffn);
|
|
447
|
+
const view = new Uint8Array(bundlerMemory.buffer, outPtr, outLen);
|
|
448
|
+
const code = decoder.decode(view.slice());
|
|
449
|
+
bundler.dealloc(outPtr, outLen);
|
|
450
|
+
return { code };
|
|
451
|
+
} finally {
|
|
452
|
+
bundler.dealloc(entryPtr, entryBytes.length);
|
|
453
|
+
if (optsPtr)
|
|
454
|
+
bundler.dealloc(optsPtr, optsLen);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
function buildChunks(entryPath, options) {
|
|
458
|
+
if (!bundler || !bundlerMemory) {
|
|
459
|
+
throw new Error("zntc-wasm: bundler not initialized. Call initBundler() first.");
|
|
460
|
+
}
|
|
461
|
+
const entryBytes = encoder.encode(entryPath);
|
|
462
|
+
const entryPtr = bundler.alloc(entryBytes.length);
|
|
463
|
+
if (entryPtr === 0)
|
|
464
|
+
throw new Error("zntc-wasm: bundler alloc failed");
|
|
465
|
+
new Uint8Array(bundlerMemory.buffer, entryPtr, entryBytes.length).set(entryBytes);
|
|
466
|
+
const { ptr: optsPtr, len: optsLen } = encodeBundleOptions(options);
|
|
467
|
+
try {
|
|
468
|
+
const packed = bundler.build_chunks(entryPtr, entryBytes.length, optsPtr, optsLen);
|
|
469
|
+
if (packed === 0n)
|
|
470
|
+
return null;
|
|
471
|
+
const outPtr = Number(packed >> 32n);
|
|
472
|
+
const outLen = Number(packed & 0xffffffffn);
|
|
473
|
+
const view = new Uint8Array(bundlerMemory.buffer, outPtr, outLen);
|
|
474
|
+
const json = decoder.decode(view.slice());
|
|
475
|
+
bundler.dealloc(outPtr, outLen);
|
|
476
|
+
return JSON.parse(json);
|
|
477
|
+
} finally {
|
|
478
|
+
bundler.dealloc(entryPtr, entryBytes.length);
|
|
479
|
+
if (optsPtr)
|
|
480
|
+
bundler.dealloc(optsPtr, optsLen);
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
export {
|
|
484
|
+
transpile,
|
|
485
|
+
initSync,
|
|
486
|
+
initBundler,
|
|
487
|
+
init,
|
|
488
|
+
bundlerVersion,
|
|
489
|
+
bundlerLastErrorMessage,
|
|
490
|
+
buildChunks,
|
|
491
|
+
build,
|
|
492
|
+
VirtualFileSystem
|
|
493
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Engine × Feature 지원 버전 테이블 (JS 미러).
|
|
3
|
+
*
|
|
4
|
+
* src/transformer/compat.zig의 compat_table을 거울 복사.
|
|
5
|
+
* browserslist → UnsupportedFeatures bitmask 계산에 사용.
|
|
6
|
+
*
|
|
7
|
+
* **주의**: compat.zig를 수정하면 이 파일도 함께 업데이트.
|
|
8
|
+
* 장기적으론 scripts/compat-from-kangax.ts를 확장해 자동 생성.
|
|
9
|
+
*
|
|
10
|
+
* Bit 레이아웃은 packages/shared/index.ts ES_TARGET_BITS와 동일 (0-27).
|
|
11
|
+
*/
|
|
12
|
+
export type Engine = 'chrome' | 'firefox' | 'safari' | 'edge' | 'node' | 'deno' | 'ios' | 'opera' | 'hermes';
|
|
13
|
+
/** compat.zig의 Feature enum과 동일 순서. bit 위치 = 배열 인덱스. */
|
|
14
|
+
export declare const FEATURES: readonly ["arrow", "class", "template_literal", "destructuring", "for_of", "spread", "object_extensions", "default_params", "block_scoping", "generator", "new_target", "exponentiation", "async_await", "object_spread", "optional_catch_binding", "nullish_coalescing", "optional_chaining", "logical_assignment", "class_static_block", "class_private_method", "class_private_field", "top_level_await", "hashbang", "using", "regex_sticky", "regex_dotall", "regex_named_groups", "unicode_brace_escape"];
|
|
15
|
+
export type Feature = (typeof FEATURES)[number];
|
|
16
|
+
/**
|
|
17
|
+
* feature × engine → 최소 지원 버전 [major, minor].
|
|
18
|
+
* 엔진에 키가 없으면 "해당 엔진에서 미지원" (compat.zig의 보수적 해석).
|
|
19
|
+
*/
|
|
20
|
+
export declare const SUPPORT: Partial<Record<Feature, Partial<Record<Engine, [number, number]>>>>;
|
|
21
|
+
export type EngineVersion = {
|
|
22
|
+
engine: Engine;
|
|
23
|
+
major: number;
|
|
24
|
+
minor: number;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* 엔진 목록에 대해 unsupported feature bitmask 계산.
|
|
28
|
+
* 하나라도 미지원인 feature는 set (가장 보수적).
|
|
29
|
+
*/
|
|
30
|
+
export declare function computeUnsupportedFromEngines(engines: EngineVersion[]): number;
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @zntc/shared — Types and utilities shared by @zntc/core and @zntc/wasm.
|
|
3
|
+
*/
|
|
4
|
+
export type Target = 'es5' | 'es2015' | 'es2016' | 'es2017' | 'es2018' | 'es2019' | 'es2020' | 'es2021' | 'es2022' | 'es2023' | 'es2024' | 'es2025' | 'esnext';
|
|
5
|
+
export type Platform = 'browser' | 'node' | 'neutral' | 'react-native';
|
|
6
|
+
export interface TranspileOptions {
|
|
7
|
+
/** File path (used for extension detection, default: "input.ts"). */
|
|
8
|
+
filename?: string;
|
|
9
|
+
/** Generate a source map. */
|
|
10
|
+
sourcemap?: boolean;
|
|
11
|
+
/** Source map Debug ID (Sentry-compatible). */
|
|
12
|
+
sourcemapDebugIds?: boolean;
|
|
13
|
+
/** Include the original source in the source map (default: true). */
|
|
14
|
+
sourcesContent?: boolean;
|
|
15
|
+
/** Minify whitespace. */
|
|
16
|
+
minifyWhitespace?: boolean;
|
|
17
|
+
/** Minify identifiers. */
|
|
18
|
+
minifyIdentifiers?: boolean;
|
|
19
|
+
/** Minify syntax. */
|
|
20
|
+
minifySyntax?: boolean;
|
|
21
|
+
/** Full minification (whitespace + identifiers + syntax). */
|
|
22
|
+
minify?: boolean;
|
|
23
|
+
/** JSX runtime. `'preserve'` emits JSX unchanged — only TypeScript annotations
|
|
24
|
+
* are stripped. Use this to delegate JSX handling to a downstream tool (e.g.
|
|
25
|
+
* @vitejs/plugin-react, @preact/preset-vite, vite-plugin-solid). Equivalent to
|
|
26
|
+
* tsc `"jsx": "preserve"`. */
|
|
27
|
+
jsx?: 'classic' | 'automatic' | 'automatic-dev' | 'preserve';
|
|
28
|
+
/** classic-mode JSX factory (default: "React.createElement"). */
|
|
29
|
+
jsxFactory?: string;
|
|
30
|
+
/** classic-mode Fragment factory (default: "React.Fragment"). */
|
|
31
|
+
jsxFragment?: string;
|
|
32
|
+
/** automatic-mode import source (default: "react"). */
|
|
33
|
+
jsxImportSource?: string;
|
|
34
|
+
/** Allow JSX in .js files as well. */
|
|
35
|
+
jsxInJs?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* React Fast Refresh transform — registers components via
|
|
38
|
+
* `$RefreshReg$(_c, "Name")`. Equivalent to the SWC builtin
|
|
39
|
+
* `jsc.transform.react.refresh: true` / babel-plugin-react-refresh component
|
|
40
|
+
* registration. Used by loaders (rspack-loader, webpack/vite plugin) when
|
|
41
|
+
* enabled on the single-file transpile path.
|
|
42
|
+
*
|
|
43
|
+
* The default behavior is Metro-compatible (registration only, no hook
|
|
44
|
+
* signatures). The babel/SWC-equivalent hook signature emit is opt-in via
|
|
45
|
+
* `reactRefreshHookSignatures: true`. Defining the HMR runtime
|
|
46
|
+
* ($RefreshReg$/$RefreshSig$) is the consumer's responsibility.
|
|
47
|
+
*/
|
|
48
|
+
reactRefresh?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* On top of `reactRefresh: true`, adds hook signature emit
|
|
51
|
+
* (`var _s = $RefreshSig$();` + `_s(Component, "sig")`). Equivalent to
|
|
52
|
+
* babel-plugin-react-refresh. Default false — preserves the Metro policy
|
|
53
|
+
* (no signatures).
|
|
54
|
+
*
|
|
55
|
+
* When enabled, the transformer scans hook calls inside function bodies to
|
|
56
|
+
* build the signature string, then emits a `_s(Comp, "sig")` call right after
|
|
57
|
+
* component registration. RN HMR keeps the default (false), so it is
|
|
58
|
+
* unaffected.
|
|
59
|
+
*/
|
|
60
|
+
reactRefreshHookSignatures?: boolean;
|
|
61
|
+
/** Remove console.* calls. */
|
|
62
|
+
dropConsole?: boolean;
|
|
63
|
+
/** Remove debugger statements. */
|
|
64
|
+
dropDebugger?: boolean;
|
|
65
|
+
/** Escape non-ASCII to \uXXXX. */
|
|
66
|
+
asciiOnly?: boolean;
|
|
67
|
+
/** Do not escape non-ASCII. */
|
|
68
|
+
charsetUtf8?: boolean;
|
|
69
|
+
/** Strip Flow types. */
|
|
70
|
+
flow?: boolean;
|
|
71
|
+
/** legacy decorator transform. */
|
|
72
|
+
experimentalDecorators?: boolean;
|
|
73
|
+
/** decorator metadata emit */
|
|
74
|
+
emitDecoratorMetadata?: boolean;
|
|
75
|
+
/** Transform class fields → `constructor` this.x = v (default: true). */
|
|
76
|
+
useDefineForClassFields?: boolean;
|
|
77
|
+
/** verbatimModuleSyntax (TS 5.0+): when true, unused value imports are not elided. */
|
|
78
|
+
verbatimModuleSyntax?: boolean;
|
|
79
|
+
/**
|
|
80
|
+
* Path to tsconfig.json (file or directory). When set, compilerOptions are
|
|
81
|
+
* auto-loaded and merged. Fields set explicitly via JS options take
|
|
82
|
+
* precedence — only unspecified fields are filled from the tsconfig values.
|
|
83
|
+
* e.g. "./tsconfig.json" or "./project-dir".
|
|
84
|
+
*/
|
|
85
|
+
tsconfigPath?: string;
|
|
86
|
+
/**
|
|
87
|
+
* Inline tsconfig JSON string (same meaning as esbuild's `tsconfigRaw`).
|
|
88
|
+
* When set, both `tsconfigPath` and autodiscovery are ignored — raw is the
|
|
89
|
+
* single source of truth. The Zig-side `tsconfig_merge` applies
|
|
90
|
+
* compilerOptions such as jsx/target/decorators directly.
|
|
91
|
+
*/
|
|
92
|
+
tsconfigRaw?: string;
|
|
93
|
+
/** Module format. */
|
|
94
|
+
format?: 'esm' | 'cjs';
|
|
95
|
+
/** String quote style. */
|
|
96
|
+
quotes?: 'double' | 'single' | 'preserve';
|
|
97
|
+
/** Target platform. */
|
|
98
|
+
platform?: Platform;
|
|
99
|
+
/** ES downlevel target. */
|
|
100
|
+
target?: Target;
|
|
101
|
+
/**
|
|
102
|
+
* browserslist query (e.g. "last 2 versions", ">1%, not dead").
|
|
103
|
+
* Takes precedence over target when set. Resolved only in the core package
|
|
104
|
+
* (depends on browserslist).
|
|
105
|
+
*/
|
|
106
|
+
browserslist?: string | string[];
|
|
107
|
+
/** The source map's sourceRoot field (default: empty string). */
|
|
108
|
+
sourceRoot?: string;
|
|
109
|
+
/**
|
|
110
|
+
* Identifier substitution pairs. `value` is raw JSON (strings must include
|
|
111
|
+
* the surrounding quotes).
|
|
112
|
+
* e.g. `[{ key: "process.env.NODE_ENV", value: "\"production\"" }]`
|
|
113
|
+
*/
|
|
114
|
+
define?: Array<{
|
|
115
|
+
key: string;
|
|
116
|
+
value: string;
|
|
117
|
+
}>;
|
|
118
|
+
/**
|
|
119
|
+
* Pipeline early-exit point — for debug/profile. When set, all stages after
|
|
120
|
+
* the given phase are skipped and empty output is returned. Useful combined
|
|
121
|
+
* with `profile` to measure a specific phase's cost in isolation.
|
|
122
|
+
*
|
|
123
|
+
* - "scan": Scanner token drain only
|
|
124
|
+
* - "parse": after Parser AST construction
|
|
125
|
+
* - "semantic": after the Semantic analyzer
|
|
126
|
+
* - "transform": after the Transformer
|
|
127
|
+
* - "codegen": full run (same as the default behavior)
|
|
128
|
+
*/
|
|
129
|
+
stopAfter?: 'scan' | 'parse' | 'semantic' | 'transform' | 'codegen';
|
|
130
|
+
}
|
|
131
|
+
export interface TranspileResult {
|
|
132
|
+
/** Transformed JavaScript code. */
|
|
133
|
+
code: string;
|
|
134
|
+
/** Source map JSON (when sourcemap: true). */
|
|
135
|
+
map?: string;
|
|
136
|
+
/**
|
|
137
|
+
* Full error text rendered in the same format as the CLI when semantic
|
|
138
|
+
* errors are present. tsc-compatible policy: code is still returned even
|
|
139
|
+
* when there are errors. Playgrounds/IDEs parse this field to display
|
|
140
|
+
* markers.
|
|
141
|
+
*/
|
|
142
|
+
errors?: string;
|
|
143
|
+
}
|
|
144
|
+
export declare const ES_TARGET_BITS: Record<string, number>;
|
|
145
|
+
export declare function targetToUnsupported(target?: Target): number;
|
|
146
|
+
/**
|
|
147
|
+
* Narrows whether `value` is a plain object (non-null, not an array).
|
|
148
|
+
* Use this to narrow a value of unknown shape — such as a `JSON.parse` result
|
|
149
|
+
* or a dynamic config object — to `Record<string, unknown>`. Shared across
|
|
150
|
+
* functional config / workspace entries / tsconfigRaw validation, etc.
|
|
151
|
+
*/
|
|
152
|
+
export declare function isPlainObject(value: unknown): value is Record<string, unknown>;
|
|
153
|
+
/**
|
|
154
|
+
* Pre-validates user-supplied `tsconfigRaw` input.
|
|
155
|
+
*
|
|
156
|
+
* NAPI (`napi_entry.zig` / `transpile.zig`) silently falls back to an empty
|
|
157
|
+
* TsConfig on raw parse failure, so an invalid raw passed through looks to the
|
|
158
|
+
* user as if the option were ignored. Called from both the CLI and JS API
|
|
159
|
+
* entry points so they uniformly throw the same explicit error
|
|
160
|
+
* (`failed to parse --tsconfig-raw: ...`). No-op when undefined.
|
|
161
|
+
*/
|
|
162
|
+
export declare function validateTsConfigRaw(raw: string | undefined): void;
|
|
163
|
+
/**
|
|
164
|
+
* Serializes TranspileOptions into Zig `ConfigOptionsDto` JSON.
|
|
165
|
+
*
|
|
166
|
+
* - Default values are omitted (minimizes payload size).
|
|
167
|
+
* - enum keys match the Zig enum name (e.g. "react-native" → "react_native").
|
|
168
|
+
* - The browserslist resolution result can be injected as the
|
|
169
|
+
* `unsupportedOverride` number. When set, it takes precedence over the
|
|
170
|
+
* `target`-based fallback on the Zig side.
|
|
171
|
+
* - `define` is serialized as a `[{ key, value }]` array (compatible with Zig
|
|
172
|
+
* DefineEntry).
|
|
173
|
+
*/
|
|
174
|
+
export declare function buildOptionsJson(opts?: TranspileOptions, unsupportedOverride?: number): string;
|
|
175
|
+
export type { Engine, EngineVersion, Feature } from './compat-engines';
|
|
176
|
+
export { computeUnsupportedFromEngines, FEATURES } from './compat-engines';
|
|
177
|
+
import type { EngineVersion } from './compat-engines';
|
|
178
|
+
/** browserslist result string ("chrome 100", "ios_saf 14.5") → EngineVersion. */
|
|
179
|
+
export declare function parseBrowserslistEntry(entry: string): EngineVersion | null;
|
|
180
|
+
/**
|
|
181
|
+
* browserslist result string array → unsupported bitmask.
|
|
182
|
+
* Unmappable engines (samsung, kaios, etc.) are ignored (engines ZNTC does not
|
|
183
|
+
* target).
|
|
184
|
+
*/
|
|
185
|
+
export declare function browserslistToUnsupported(entries: string[]): number;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @zntc/wasm — ZNTC TypeScript 트랜스파일러 WASM 바인딩
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```ts
|
|
6
|
+
* import { init, transpile } from "@zntc/wasm";
|
|
7
|
+
* await init();
|
|
8
|
+
* const result = transpile("const x: number = 1;", { target: "es5" });
|
|
9
|
+
* console.log(result.code);
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export type { Target, Platform, TranspileOptions, TranspileResult } from '../shared/index';
|
|
13
|
+
import type { Target, TranspileOptions, TranspileResult } from '../shared/index';
|
|
14
|
+
export declare function init(input?: URL | string | Request | Response | BufferSource | WebAssembly.Module): Promise<void>;
|
|
15
|
+
export declare function initSync(input: WebAssembly.Module | BufferSource): void;
|
|
16
|
+
export declare function transpile(source: string, options?: TranspileOptions): TranspileResult;
|
|
17
|
+
export declare class VirtualFileSystem {
|
|
18
|
+
private files;
|
|
19
|
+
set(path: string, content: string | Uint8Array): void;
|
|
20
|
+
get(path: string): Uint8Array | undefined;
|
|
21
|
+
has(path: string): boolean;
|
|
22
|
+
delete(path: string): boolean;
|
|
23
|
+
paths(): IterableIterator<string>;
|
|
24
|
+
size(): number;
|
|
25
|
+
clear(): void;
|
|
26
|
+
}
|
|
27
|
+
export declare function initBundler(vfs: VirtualFileSystem, input?: URL | string | Request | Response | BufferSource | WebAssembly.Module): Promise<void>;
|
|
28
|
+
export declare function bundlerVersion(): number;
|
|
29
|
+
export interface BundleResult {
|
|
30
|
+
code: string;
|
|
31
|
+
}
|
|
32
|
+
export interface BundleOptionsInput {
|
|
33
|
+
format?: 'esm' | 'cjs' | 'iife' | 'umd' | 'amd';
|
|
34
|
+
platform?: 'browser' | 'node' | 'neutral' | 'react-native';
|
|
35
|
+
external?: string[];
|
|
36
|
+
minify?: boolean;
|
|
37
|
+
minifyWhitespace?: boolean;
|
|
38
|
+
minifyIdentifiers?: boolean;
|
|
39
|
+
minifySyntax?: boolean;
|
|
40
|
+
codeSplitting?: boolean;
|
|
41
|
+
preserveModules?: boolean;
|
|
42
|
+
target?: Target;
|
|
43
|
+
unsupported?: number;
|
|
44
|
+
jsx?: 'classic' | 'automatic' | 'automatic-dev';
|
|
45
|
+
jsxFactory?: string;
|
|
46
|
+
jsxFragment?: string;
|
|
47
|
+
jsxImportSource?: string;
|
|
48
|
+
flow?: boolean;
|
|
49
|
+
jsxInJs?: boolean;
|
|
50
|
+
experimentalDecorators?: boolean;
|
|
51
|
+
emitDecoratorMetadata?: boolean;
|
|
52
|
+
useDefineForClassFields?: boolean;
|
|
53
|
+
charsetUtf8?: boolean;
|
|
54
|
+
keepNames?: boolean;
|
|
55
|
+
sourcemap?: boolean;
|
|
56
|
+
}
|
|
57
|
+
export declare function bundlerLastErrorMessage(): string;
|
|
58
|
+
export declare function build(entryPath: string, options?: BundleOptionsInput): BundleResult | null;
|
|
59
|
+
export interface OutputChunk {
|
|
60
|
+
path: string;
|
|
61
|
+
code: string;
|
|
62
|
+
}
|
|
63
|
+
export declare function buildChunks(entryPath: string, options?: BundleOptionsInput): OutputChunk[] | null;
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@zntc/wasm",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "ZNTC native transpiler & compiler — WASM build",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"browser",
|
|
7
|
+
"bundler",
|
|
8
|
+
"compiler",
|
|
9
|
+
"deno",
|
|
10
|
+
"javascript",
|
|
11
|
+
"transpiler",
|
|
12
|
+
"typescript",
|
|
13
|
+
"wasm",
|
|
14
|
+
"webassembly",
|
|
15
|
+
"workers",
|
|
16
|
+
"zntc"
|
|
17
|
+
],
|
|
18
|
+
"homepage": "https://ohah.github.io/zntc",
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://github.com/ohah/zntc/issues"
|
|
21
|
+
},
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"author": "ohah",
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "git+https://github.com/ohah/zntc.git",
|
|
27
|
+
"directory": "packages/wasm"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"dist/",
|
|
31
|
+
"zntc.wasm",
|
|
32
|
+
"zntc-bundler.wasm"
|
|
33
|
+
],
|
|
34
|
+
"type": "module",
|
|
35
|
+
"main": "dist/index.js",
|
|
36
|
+
"types": "dist/wasm/index.d.ts",
|
|
37
|
+
"exports": {
|
|
38
|
+
".": {
|
|
39
|
+
"types": "./dist/wasm/index.d.ts",
|
|
40
|
+
"import": "./dist/index.js"
|
|
41
|
+
},
|
|
42
|
+
"./zntc.wasm": "./zntc.wasm",
|
|
43
|
+
"./zntc-bundler.wasm": "./zntc-bundler.wasm"
|
|
44
|
+
},
|
|
45
|
+
"scripts": {
|
|
46
|
+
"build:wasm": "cd ../.. && zig build wasm && zig build wasm-bundler",
|
|
47
|
+
"build:js": "bun build index.ts --outdir dist --format esm --target browser --external 'node:*'",
|
|
48
|
+
"build:dts": "bun x tsc -b",
|
|
49
|
+
"build": "bun run build:wasm && cp ../../zig-out/bin/zntc.wasm . && cp ../../zig-out/bin/zntc-bundler.wasm . && bun run build:js && bun run build:dts",
|
|
50
|
+
"test": "bun test --timeout 10000",
|
|
51
|
+
"prepublishOnly": "bun run build && bunx publint --strict --level error ."
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@types/node": "^25.5.2"
|
|
55
|
+
},
|
|
56
|
+
"engines": {
|
|
57
|
+
"node": ">=24.0.0"
|
|
58
|
+
}
|
|
59
|
+
}
|
|
Binary file
|
package/zntc.wasm
ADDED
|
Binary file
|