xbintsc 0.3.14 → 0.3.16

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 (201) hide show
  1. package/README.md +22 -22
  2. package/README.zh-CN.md +20 -19
  3. package/bin/xbintsc.js +1 -2
  4. package/dist/src/cli/main.js +8 -5
  5. package/dist/src/cli/main.js.map +1 -1
  6. package/dist/src/codegen/generator/state.js +8 -0
  7. package/dist/src/codegen/generator/state.js.map +1 -1
  8. package/dist/src/codegen/generator/tables.d.ts +5 -6
  9. package/dist/src/codegen/generator/tables.js +13 -6
  10. package/dist/src/codegen/generator/tables.js.map +1 -1
  11. package/dist/src/driver/bundler/graph.d.ts +8 -0
  12. package/dist/src/driver/bundler/graph.js +85 -0
  13. package/dist/src/driver/bundler/graph.js.map +1 -0
  14. package/dist/src/driver/bundler/merge.d.ts +11 -0
  15. package/dist/src/driver/bundler/merge.js +288 -0
  16. package/dist/src/driver/bundler/merge.js.map +1 -0
  17. package/dist/src/driver/bundler/resolve.d.ts +12 -0
  18. package/dist/src/driver/bundler/resolve.js +246 -0
  19. package/dist/src/driver/bundler/resolve.js.map +1 -0
  20. package/dist/src/driver/bundler/symbols.d.ts +15 -0
  21. package/dist/src/driver/bundler/symbols.js +51 -0
  22. package/dist/src/driver/bundler/symbols.js.map +1 -0
  23. package/dist/src/driver/bundler/types.d.ts +36 -0
  24. package/dist/src/driver/bundler/types.js +5 -0
  25. package/dist/src/driver/bundler/types.js.map +1 -0
  26. package/dist/src/driver/index.d.ts +1 -2
  27. package/dist/src/driver/index.js +1 -2
  28. package/dist/src/driver/index.js.map +1 -1
  29. package/dist/src/driver/modules.d.ts +9 -16
  30. package/dist/src/driver/modules.js +8 -644
  31. package/dist/src/driver/modules.js.map +1 -1
  32. package/dist/src/driver/paths.d.ts +0 -9
  33. package/dist/src/driver/paths.js +0 -31
  34. package/dist/src/driver/paths.js.map +1 -1
  35. package/dist/src/driver/toolchain-provider.d.ts +10 -10
  36. package/dist/src/driver/toolchain-provider.js +9 -38
  37. package/dist/src/driver/toolchain-provider.js.map +1 -1
  38. package/dist/src/driver/toolchain.js +8 -2
  39. package/dist/src/driver/toolchain.js.map +1 -1
  40. package/dist/src/extensions/catalog.js +2 -1
  41. package/dist/src/extensions/catalog.js.map +1 -1
  42. package/dist/src/extensions/gui/index.d.ts +24 -0
  43. package/dist/src/extensions/gui/index.js +101 -0
  44. package/dist/src/extensions/gui/index.js.map +1 -0
  45. package/dist/src/extensions/native.d.ts +2 -3
  46. package/dist/src/extensions/native.js +2 -3
  47. package/dist/src/extensions/native.js.map +1 -1
  48. package/dist/tests/driver/paths.test.js +1 -9
  49. package/dist/tests/driver/paths.test.js.map +1 -1
  50. package/dist/tests/driver/toolchain-provider.test.js +12 -79
  51. package/dist/tests/driver/toolchain-provider.test.js.map +1 -1
  52. package/dist/tests/e2e/compile-basics.test.d.ts +4 -0
  53. package/dist/tests/e2e/compile-basics.test.js +134 -0
  54. package/dist/tests/e2e/compile-basics.test.js.map +1 -0
  55. package/dist/tests/e2e/compile-builtins.test.d.ts +4 -0
  56. package/dist/tests/e2e/compile-builtins.test.js +191 -0
  57. package/dist/tests/e2e/compile-builtins.test.js.map +1 -0
  58. package/dist/tests/e2e/compile-control-flow.test.d.ts +4 -0
  59. package/dist/tests/e2e/compile-control-flow.test.js +190 -0
  60. package/dist/tests/e2e/compile-control-flow.test.js.map +1 -0
  61. package/dist/tests/e2e/compile-modules.test.d.ts +4 -0
  62. package/dist/tests/e2e/compile-modules.test.js +48 -0
  63. package/dist/tests/e2e/compile-modules.test.js.map +1 -0
  64. package/dist/tests/e2e/compile-objects-classes.test.d.ts +4 -0
  65. package/dist/tests/e2e/compile-objects-classes.test.js +362 -0
  66. package/dist/tests/e2e/compile-objects-classes.test.js.map +1 -0
  67. package/dist/tests/e2e/differential-helpers.d.ts +12 -0
  68. package/dist/tests/e2e/differential-helpers.js +16 -0
  69. package/dist/tests/e2e/differential-helpers.js.map +1 -0
  70. package/dist/tests/e2e/differential-language.test.d.ts +4 -0
  71. package/dist/tests/e2e/{differential.test.js → differential-language.test.js} +5 -287
  72. package/dist/tests/e2e/differential-language.test.js.map +1 -0
  73. package/dist/tests/e2e/differential-symbols.test.d.ts +4 -0
  74. package/dist/tests/e2e/differential-symbols.test.js +92 -0
  75. package/dist/tests/e2e/differential-symbols.test.js.map +1 -0
  76. package/dist/tests/e2e/differential-values.test.d.ts +4 -0
  77. package/dist/tests/e2e/differential-values.test.js +197 -0
  78. package/dist/tests/e2e/differential-values.test.js.map +1 -0
  79. package/dist/tests/e2e/gui.test.d.ts +12 -0
  80. package/dist/tests/e2e/gui.test.js +493 -0
  81. package/dist/tests/e2e/gui.test.js.map +1 -0
  82. package/dist/tests/e2e/native-extensions.test.d.ts +4 -5
  83. package/dist/tests/e2e/native-extensions.test.js +6 -7
  84. package/dist/tests/e2e/native-extensions.test.js.map +1 -1
  85. package/dist/tests/e2e/runtime-coverage-buffer.test.d.ts +4 -0
  86. package/dist/tests/e2e/runtime-coverage-buffer.test.js +97 -0
  87. package/dist/tests/e2e/runtime-coverage-buffer.test.js.map +1 -0
  88. package/dist/tests/e2e/runtime-coverage-globals.test.d.ts +4 -0
  89. package/dist/tests/e2e/runtime-coverage-globals.test.js +149 -0
  90. package/dist/tests/e2e/runtime-coverage-globals.test.js.map +1 -0
  91. package/dist/tests/e2e/runtime-coverage-node-modules.test.d.ts +4 -0
  92. package/dist/tests/e2e/runtime-coverage-node-modules.test.js +177 -0
  93. package/dist/tests/e2e/runtime-coverage-node-modules.test.js.map +1 -0
  94. package/dist/tests/e2e/runtime-coverage-streams.test.d.ts +4 -0
  95. package/dist/tests/e2e/runtime-coverage-streams.test.js +161 -0
  96. package/dist/tests/e2e/runtime-coverage-streams.test.js.map +1 -0
  97. package/dist/tests/e2e/runtime-coverage-system.test.d.ts +4 -0
  98. package/dist/tests/e2e/runtime-coverage-system.test.js +91 -0
  99. package/dist/tests/e2e/runtime-coverage-system.test.js.map +1 -0
  100. package/dist/tests/e2e/timers.test.d.ts +7 -0
  101. package/dist/tests/e2e/timers.test.js +63 -0
  102. package/dist/tests/e2e/timers.test.js.map +1 -0
  103. package/package.json +2 -2
  104. package/runtime/ext_gui/css.cpp +743 -0
  105. package/runtime/ext_gui/css.h +98 -0
  106. package/runtime/ext_gui/document.cpp +264 -0
  107. package/runtime/ext_gui/document.h +89 -0
  108. package/runtime/ext_gui/dom.cpp +472 -0
  109. package/runtime/ext_gui/dom.h +71 -0
  110. package/runtime/ext_gui/gui.cpp +457 -0
  111. package/runtime/ext_gui/gui_engine.h +81 -0
  112. package/runtime/ext_gui/image.cpp +125 -0
  113. package/runtime/ext_gui/image.h +42 -0
  114. package/runtime/ext_gui/layout.cpp +748 -0
  115. package/runtime/ext_gui/layout.h +93 -0
  116. package/runtime/ext_gui/paint.cpp +137 -0
  117. package/runtime/ext_gui/paint.h +75 -0
  118. package/runtime/ext_gui/renderer.cpp +959 -0
  119. package/runtime/ext_gui/renderer.h +68 -0
  120. package/runtime/ext_gui/stb_image.h +7988 -0
  121. package/runtime/ext_gui/style.cpp +771 -0
  122. package/runtime/ext_gui/style.h +117 -0
  123. package/runtime/ext_gui/text.cpp +378 -0
  124. package/runtime/ext_gui/text.h +78 -0
  125. package/runtime/ext_gui/window.cpp +405 -0
  126. package/runtime/ext_node/fs/fs_common.h +13 -527
  127. package/runtime/ext_node/fs/meta_ops.c +3 -3
  128. package/runtime/ext_node/fs/parts/buffer-bridge.inc +6 -0
  129. package/runtime/ext_node/fs/parts/builtins.inc +69 -0
  130. package/runtime/ext_node/fs/parts/dir.inc +47 -0
  131. package/runtime/ext_node/fs/parts/encoding.inc +186 -0
  132. package/runtime/ext_node/fs/parts/errors.inc +66 -0
  133. package/runtime/ext_node/fs/parts/flags.inc +39 -0
  134. package/runtime/ext_node/fs/parts/platform.inc +86 -0
  135. package/runtime/ext_node/fs/parts/promisify.inc +15 -0
  136. package/runtime/ext_node/fs/parts/time.inc +9 -0
  137. package/runtime/rt.h +36 -4
  138. package/runtime/rt_internal.h +10 -23
  139. package/runtime/xt_builtins.c +4 -0
  140. package/runtime/xt_containers/access.inc +168 -0
  141. package/runtime/xt_containers/arrays.inc +108 -0
  142. package/runtime/xt_containers/boxes.inc +11 -0
  143. package/runtime/xt_containers/objects.inc +326 -0
  144. package/runtime/xt_containers.c +8 -618
  145. package/runtime/xt_ext.h +0 -1
  146. package/runtime/xt_io/base64.inc +87 -0
  147. package/runtime/xt_io/console.inc +119 -0
  148. package/runtime/xt_io/exception.inc +142 -0
  149. package/runtime/xt_io/inspect.inc +212 -0
  150. package/runtime/xt_io.c +11 -556
  151. package/runtime/xt_loop.c +262 -24
  152. package/runtime/xt_regex/api.inc +58 -0
  153. package/runtime/xt_regex/helpers.inc +68 -0
  154. package/runtime/xt_regex/matcher.inc +248 -0
  155. package/runtime/xt_regex/parser.inc +236 -0
  156. package/runtime/xt_regex/types.inc +58 -0
  157. package/runtime/xt_regex.h +9 -672
  158. package/runtime/xt_stdlib2/helpers.inc +2 -4
  159. package/runtime/xt_values/arithmetic.inc +150 -0
  160. package/runtime/xt_values/comparison.inc +112 -0
  161. package/runtime/xt_values/constructors.inc +41 -0
  162. package/runtime/xt_values/conversions.inc +115 -0
  163. package/runtime/xt_values/number-format.inc +180 -0
  164. package/runtime/xt_values/strings.inc +22 -0
  165. package/runtime/xt_values.c +10 -626
  166. package/scripts/build-gui.ts +317 -0
  167. package/scripts/build-runtime.ts +7 -8
  168. package/scripts/coverage-runtime.ts +4 -4
  169. package/scripts/package-release.ts +12 -84
  170. package/src/cli/main.ts +8 -4
  171. package/src/codegen/generator/state.ts +8 -0
  172. package/src/codegen/generator/tables.ts +13 -6
  173. package/src/driver/bundler/graph.ts +95 -0
  174. package/src/driver/bundler/merge.ts +312 -0
  175. package/src/driver/bundler/resolve.ts +240 -0
  176. package/src/driver/bundler/symbols.ts +55 -0
  177. package/src/driver/bundler/types.ts +37 -0
  178. package/src/driver/index.ts +1 -9
  179. package/src/driver/modules.ts +9 -693
  180. package/src/driver/paths.ts +0 -31
  181. package/src/driver/toolchain-provider.ts +12 -45
  182. package/src/driver/toolchain.ts +7 -2
  183. package/src/extensions/catalog.ts +2 -1
  184. package/src/extensions/gui/index.ts +107 -0
  185. package/src/extensions/native.ts +2 -3
  186. package/dist/src/driver/toolchain-download.d.ts +0 -50
  187. package/dist/src/driver/toolchain-download.js +0 -102
  188. package/dist/src/driver/toolchain-download.js.map +0 -1
  189. package/dist/tests/driver/toolchain-download.test.d.ts +0 -1
  190. package/dist/tests/driver/toolchain-download.test.js +0 -53
  191. package/dist/tests/driver/toolchain-download.test.js.map +0 -1
  192. package/dist/tests/e2e/compile.test.d.ts +0 -8
  193. package/dist/tests/e2e/compile.test.js +0 -893
  194. package/dist/tests/e2e/compile.test.js.map +0 -1
  195. package/dist/tests/e2e/differential.test.d.ts +0 -7
  196. package/dist/tests/e2e/differential.test.js.map +0 -1
  197. package/dist/tests/e2e/runtime-coverage.test.d.ts +0 -11
  198. package/dist/tests/e2e/runtime-coverage.test.js +0 -646
  199. package/dist/tests/e2e/runtime-coverage.test.js.map +0 -1
  200. package/scripts/fetch-toolchain.ts +0 -101
  201. package/src/driver/toolchain-download.ts +0 -135
@@ -0,0 +1,317 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Build the GUI extension archive:
4
+ *
5
+ * runtime/lib/<os>-<arch>/gui.a
6
+ *
7
+ * The archive bundles the engine (`runtime/ext_gui/*.cpp`) together with a
8
+ * statically built SDL3, so a released compiler links GUI programs with no
9
+ * external dependency beyond the OS frameworks declared by
10
+ * `src/extensions/gui/index.ts`.
11
+ *
12
+ * Steps:
13
+ * 1. fetch the pinned SDL3 source into `vendor/SDL` (gitignored),
14
+ * 2. build `libSDL3.a` with CMake,
15
+ * 2b. fetch + build static FreeType and HarfBuzz for text,
16
+ * 3. compile the engine translation units,
17
+ * 4. merge everything into `gui.a` (libtool on macOS, `ar -M` elsewhere;
18
+ * `gui.lib` on Windows, built from MSVC-compatible COFF objects).
19
+ *
20
+ * Environment:
21
+ * xbintsc_CXX C++ compiler override (default: clang++/c++/g++)
22
+ * xbintsc_CMAKE CMake override (default: a vendored CMake, then `cmake`)
23
+ * xbintsc_AR archiver override (default: llvm-ar, then ar)
24
+ * SDL3_TAG SDL3 git tag to check out (default: release-3.2.10)
25
+ * FREETYPE_VERSION FreeType version (default: 2.13.3)
26
+ * HARFBUZZ_VERSION HarfBuzz version (default: 10.1.0)
27
+ *
28
+ * On Windows the engine is compiled with `clang++` against the MSVC ABI (run
29
+ * from a Visual Studio developer prompt so `INCLUDE`/`LIB` are set) and merged
30
+ * into a COFF `gui.lib` with `llvm-ar`.
31
+ */
32
+
33
+ import { existsSync, mkdirSync, readdirSync, renameSync, rmSync } from "node:fs";
34
+ import { spawnSync, type SpawnSyncReturns } from "node:child_process";
35
+ import { dirname, join, resolve } from "node:path";
36
+ import { fileURLToPath } from "node:url";
37
+ import { platformSlug } from "../src/driver/paths.js";
38
+
39
+ const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
40
+ const runtimeDir = join(root, "runtime");
41
+ const engineDir = join(runtimeDir, "ext_gui");
42
+ const vendorDir = join(root, "vendor");
43
+ const sdlSrc = join(vendorDir, "SDL");
44
+ const sdlBuild = join(sdlSrc, "build");
45
+ const freetypeSrc = join(vendorDir, "freetype");
46
+ const freetypeBuild = join(vendorDir, "freetype-build");
47
+ const harfbuzzSrc = join(vendorDir, "harfbuzz");
48
+ const harfbuzzBuild = join(vendorDir, "harfbuzz-build");
49
+ const objDir = join(root, "build", "gui-obj");
50
+ const outDir = join(runtimeDir, "lib", platformSlug());
51
+
52
+ const isWindows = process.platform === "win32";
53
+ const objectSuffix = isWindows ? ".obj" : ".o";
54
+ const output = join(outDir, isWindows ? "gui.lib" : "gui.a");
55
+
56
+ const SDL_TAG = process.env.SDL3_TAG || "release-3.2.10";
57
+ const FREETYPE_VERSION = process.env.FREETYPE_VERSION || "2.13.3";
58
+ const HARFBUZZ_VERSION = process.env.HARFBUZZ_VERSION || "10.1.0";
59
+ const FREETYPE_URL = `https://download.savannah.gnu.org/releases/freetype/freetype-${FREETYPE_VERSION}.tar.xz`;
60
+ const HARFBUZZ_URL = `https://github.com/harfbuzz/harfbuzz/releases/download/${HARFBUZZ_VERSION}/harfbuzz-${HARFBUZZ_VERSION}.tar.xz`;
61
+
62
+ function fail(message: string): never {
63
+ console.error(`xbintsc: ${message}`);
64
+ process.exit(1);
65
+ }
66
+
67
+ function run(
68
+ command: string,
69
+ args: readonly string[],
70
+ options: { input?: string; quietStderr?: boolean } = {},
71
+ ): SpawnSyncReturns<string> {
72
+ const quiet = options.quietStderr === true;
73
+ const result = spawnSync(command, args, {
74
+ stdio: options.input !== undefined ? ["pipe", "inherit", "inherit"] : quiet ? ["ignore", "inherit", "pipe"] : "inherit",
75
+ encoding: "utf8",
76
+ input: options.input,
77
+ });
78
+ if (result.status !== 0) {
79
+ if (quiet && result.stderr) process.stderr.write(result.stderr);
80
+ fail(`${command} ${args.join(" ")} failed with status ${result.status ?? "?"}`);
81
+ }
82
+ return result;
83
+ }
84
+
85
+ function isRunnable(candidate: string): boolean {
86
+ return !spawnSync(candidate, ["--version"], { encoding: "utf8" }).error;
87
+ }
88
+
89
+ function firstAvailable(candidates: readonly (string | undefined)[]): string | undefined {
90
+ for (const candidate of candidates) {
91
+ if (candidate && isRunnable(candidate)) return candidate;
92
+ }
93
+ return undefined;
94
+ }
95
+
96
+ /** Vendored CMake from `vendor/tools`, then `cmake` on PATH. */
97
+ function findCmake(): string {
98
+ const candidates: string[] = [];
99
+ if (process.env.xbintsc_CMAKE) candidates.push(process.env.xbintsc_CMAKE);
100
+ if (existsSync(join(vendorDir, "tools"))) {
101
+ for (const entry of readdirSync(join(vendorDir, "tools"))) {
102
+ if (!entry.startsWith("cmake-")) continue;
103
+ candidates.push(join(vendorDir, "tools", entry, "CMake.app", "Contents", "bin", "cmake"));
104
+ candidates.push(join(vendorDir, "tools", entry, "bin", "cmake"));
105
+ }
106
+ }
107
+ candidates.push("cmake");
108
+ const cmake = firstAvailable(candidates);
109
+ if (!cmake) fail("no CMake found; install it or set xbintsc_CMAKE");
110
+ return cmake;
111
+ }
112
+
113
+ function findCxx(): string {
114
+ const cxx = firstAvailable([process.env.xbintsc_CXX, "clang++", "c++", "g++"]);
115
+ if (!cxx) fail("no C++ compiler found; install clang++ or set xbintsc_CXX");
116
+ return cxx;
117
+ }
118
+
119
+ function findArchiver(): string {
120
+ const ar = firstAvailable([process.env.xbintsc_AR, "llvm-ar", "ar"]);
121
+ if (!ar) fail("no archiver found; set xbintsc_AR to llvm-ar or ar");
122
+ return ar;
123
+ }
124
+
125
+ /** First of `candidates` that exists on disk (CMake generators place static
126
+ * libraries either at the build root or under `Release/`). */
127
+ function firstExisting(candidates: readonly string[]): string | undefined {
128
+ for (const candidate of candidates) {
129
+ if (existsSync(candidate)) return candidate;
130
+ }
131
+ return undefined;
132
+ }
133
+
134
+ /** Locate a library CMake produced, accepting the POSIX and MSVC names and
135
+ * falling back to a version-suffixed MSVC name (e.g. `freetype-2.13.3.lib`). */
136
+ function builtLibrary(buildDir: string, names: readonly string[], pattern?: RegExp): string | undefined {
137
+ const candidates: string[] = [];
138
+ for (const name of names) {
139
+ candidates.push(join(buildDir, name));
140
+ candidates.push(join(buildDir, "Release", name));
141
+ candidates.push(join(buildDir, "Debug", name));
142
+ }
143
+ const exact = firstExisting(candidates);
144
+ if (exact || !pattern) return exact;
145
+ for (const dir of [buildDir, join(buildDir, "Release"), join(buildDir, "Debug")]) {
146
+ if (!existsSync(dir)) continue;
147
+ for (const entry of readdirSync(dir)) {
148
+ if (pattern.test(entry)) return join(dir, entry);
149
+ }
150
+ }
151
+ return undefined;
152
+ }
153
+
154
+ function sdlArchive(): string | undefined {
155
+ return builtLibrary(sdlBuild, ["libSDL3.a", "SDL3-static.lib", "SDL3.lib"], /^SDL3[-\w.]*\.lib$/);
156
+ }
157
+ function freetypeArchive(): string | undefined {
158
+ return builtLibrary(freetypeBuild, ["libfreetype.a", "freetype.lib"], /^freetype[-\d.]*\.lib$/);
159
+ }
160
+ function harfbuzzArchive(): string | undefined {
161
+ return builtLibrary(harfbuzzBuild, ["libharfbuzz.a", "harfbuzz.lib"], /^harfbuzz[-\d.]*\.lib$/);
162
+ }
163
+
164
+ /* -- 1. SDL3 source ------------------------------------------------------- */
165
+
166
+ if (!existsSync(join(sdlSrc, "CMakeLists.txt"))) {
167
+ console.log(`xbintsc: fetching SDL3 ${SDL_TAG} into vendor/SDL`);
168
+ mkdirSync(vendorDir, { recursive: true });
169
+ run("git", ["clone", "--depth", "1", "--branch", SDL_TAG, "https://github.com/libsdl-org/SDL.git", sdlSrc]);
170
+ }
171
+
172
+ /* -- 2. static SDL3 ------------------------------------------------------- */
173
+
174
+ const existingSdlArchive = sdlArchive();
175
+ if (!existingSdlArchive) {
176
+ const cmake = findCmake();
177
+ console.log(`xbintsc: building static SDL3 with ${cmake}`);
178
+ const configureArgs = [
179
+ "-S", sdlSrc,
180
+ "-B", sdlBuild,
181
+ "-DCMAKE_BUILD_TYPE=Release",
182
+ "-DSDL_SHARED=OFF",
183
+ "-DSDL_STATIC=ON",
184
+ "-DSDL_TESTS=OFF",
185
+ "-DSDL_EXAMPLES=OFF",
186
+ ];
187
+ run(cmake, configureArgs);
188
+ run(cmake, ["--build", sdlBuild, "--config", "Release", "--target", "SDL3-static", "--parallel"]);
189
+ } else {
190
+ console.log(`xbintsc: reusing existing ${existingSdlArchive}`);
191
+ }
192
+
193
+ /* -- 2b. FreeType + HarfBuzz (text) --------------------------------------- */
194
+
195
+ /** Download a release tarball into `vendor/` and extract it under `name`.
196
+ * Release tarballs are used (not git clones) because they ship generated
197
+ * sources, so no ragel/autotools step is needed. */
198
+ function ensureTarballSource(name: string, url: string, extractedName: string): string {
199
+ const destination = join(vendorDir, name);
200
+ if (existsSync(join(destination, "CMakeLists.txt"))) return destination;
201
+ const tarball = join(vendorDir, `${name}.tar.xz`);
202
+ console.log(`xbintsc: fetching ${name} from ${url}`);
203
+ mkdirSync(vendorDir, { recursive: true });
204
+ run("curl", ["-sL", "--fail", "-o", tarball, url]);
205
+ run("tar", ["-xf", tarball, "-C", vendorDir]);
206
+ const extracted = join(vendorDir, extractedName);
207
+ if (!existsSync(extracted)) fail(`expected ${extractedName} after extracting ${name}`);
208
+ rmSync(destination, { recursive: true, force: true });
209
+ renameSync(extracted, destination);
210
+ rmSync(tarball, { force: true });
211
+ return destination;
212
+ }
213
+
214
+ ensureTarballSource("freetype", FREETYPE_URL, `freetype-${FREETYPE_VERSION}`);
215
+ ensureTarballSource("harfbuzz", HARFBUZZ_URL, `harfbuzz-${HARFBUZZ_VERSION}`);
216
+
217
+ if (!existsSync(freetypeArchive() ?? "")) {
218
+ const cmake = findCmake();
219
+ console.log("xbintsc: building static FreeType");
220
+ run(cmake, [
221
+ "-S", freetypeSrc,
222
+ "-B", freetypeBuild,
223
+ "-DCMAKE_BUILD_TYPE=Release",
224
+ "-DBUILD_SHARED_LIBS=OFF",
225
+ /* We only need TrueType/OpenType outlines; skip the optional codecs. */
226
+ "-DFT_DISABLE_ZLIB=TRUE",
227
+ "-DFT_DISABLE_BZIP2=TRUE",
228
+ "-DFT_DISABLE_PNG=TRUE",
229
+ "-DFT_DISABLE_HARFBUZZ=TRUE",
230
+ "-DFT_DISABLE_BROTLI=TRUE",
231
+ ]);
232
+ run(cmake, ["--build", freetypeBuild, "--config", "Release", "--parallel"]);
233
+ } else {
234
+ console.log(`xbintsc: reusing existing ${freetypeArchive()}`);
235
+ }
236
+
237
+ if (!existsSync(harfbuzzArchive() ?? "")) {
238
+ const cmake = findCmake();
239
+ console.log("xbintsc: building static HarfBuzz");
240
+ run(cmake, [
241
+ "-S", harfbuzzSrc,
242
+ "-B", harfbuzzBuild,
243
+ "-DCMAKE_BUILD_TYPE=Release",
244
+ "-DBUILD_SHARED_LIBS=OFF",
245
+ "-DHB_BUILD_UTILS=OFF",
246
+ "-DHB_BUILD_TESTS=OFF",
247
+ "-DHB_BUILD_SUBSET=OFF",
248
+ "-DHB_HAVE_FREETYPE=OFF",
249
+ "-DHB_HAVE_GLIB=OFF",
250
+ "-DHB_HAVE_ICU=OFF",
251
+ "-DHB_HAVE_GRAPHITE2=OFF",
252
+ ]);
253
+ run(cmake, ["--build", harfbuzzBuild, "--config", "Release", "--parallel"]);
254
+ } else {
255
+ console.log(`xbintsc: reusing existing ${harfbuzzArchive()}`);
256
+ }
257
+
258
+ /* -- 3. engine objects ---------------------------------------------------- */
259
+
260
+ const cxx = findCxx();
261
+ mkdirSync(objDir, { recursive: true });
262
+ const includeFlags = [
263
+ "-I", runtimeDir,
264
+ "-I", join(sdlSrc, "include"),
265
+ "-I", join(freetypeSrc, "include"),
266
+ "-I", join(freetypeBuild, "include"),
267
+ "-I", join(harfbuzzSrc, "src"),
268
+ ];
269
+ const sources = readdirSync(engineDir)
270
+ .filter((entry) => entry.endsWith(".cpp"))
271
+ .sort();
272
+
273
+ const objects: string[] = [];
274
+ const cxxFlags = ["-std=c++17", "-O2", "-Wall", "-Wextra", ...includeFlags];
275
+ /* The MSVC ABI rejects `-fPIC`; position independence is the default elsewhere. */
276
+ if (!isWindows) cxxFlags.splice(3, 0, "-fPIC");
277
+ for (const source of sources) {
278
+ const object = join(objDir, source.replace(/\.cpp$/, objectSuffix));
279
+ console.log(`xbintsc: compiling ${source}`);
280
+ run(cxx, [...cxxFlags, "-c", join(engineDir, source), "-o", object]);
281
+ objects.push(object);
282
+ }
283
+
284
+ /* -- 4. merge into gui.a / gui.lib ---------------------------------------- */
285
+
286
+ const sdl = sdlArchive();
287
+ const freetype = freetypeArchive();
288
+ const harfbuzz = harfbuzzArchive();
289
+ if (!sdl || !freetype || !harfbuzz) {
290
+ fail("one of the SDL3/FreeType/HarfBuzz archives was not found after building");
291
+ }
292
+ const libraries = [sdl, freetype, harfbuzz];
293
+
294
+ mkdirSync(outDir, { recursive: true });
295
+ rmSync(output, { force: true });
296
+ if (process.platform === "darwin") {
297
+ /* libtool warns about the empty object files SDL3's archive carries; hide it
298
+ * unless the merge actually fails. */
299
+ run("libtool", ["-static", "-o", output, ...objects, ...libraries], {
300
+ quietStderr: true,
301
+ });
302
+ } else {
303
+ /* `ar -M` (GNU/LLVM) merges archives through an MRI script. Windows paths are
304
+ * normalised to `/` so the MRI parser does not read `\` as an escape. */
305
+ const mri = (path: string): string => path.replace(/\\/g, "/");
306
+ const ar = findArchiver();
307
+ const script = [
308
+ `create ${mri(output)}`,
309
+ ...objects.map((object) => `addmod ${mri(object)}`),
310
+ ...libraries.map((library) => `addlib ${mri(library)}`),
311
+ "save",
312
+ "end",
313
+ ].join("\n");
314
+ run(ar, ["-M"], { input: script });
315
+ }
316
+
317
+ console.log(`xbintsc: wrote ${output}`);
@@ -29,16 +29,15 @@ const outDir = join(runtimeDir, "lib", platformSlug());
29
29
  const objDir = join(root, "build", "runtime-obj");
30
30
 
31
31
  if (process.platform === "win32") {
32
- // The Windows release ships no prebuilt archives yet: the current MSVC CI
33
- // cannot produce MinGW-compatible objects, so the driver compiles the C
34
- // sources on demand. Revisit once the bundled MinGW-w64 ABI lands.
35
- // See doc/self-contained-roadmap.md.
36
- console.log("xbintsc: skipped runtime archives on Windows until the MinGW-w64 toolchain lands");
32
+ // The driver links with the MSVC ABI on Windows, where the prebuilt archives
33
+ // are unnecessary: `build` compiles the runtime C sources on demand with the
34
+ // user's clang. (Producing MSVC-compatible COFF `.lib` archives is possible
35
+ // but not worth the extra step.)
36
+ console.log("xbintsc: skipping runtime archives on Windows; the driver compiles the C sources on demand");
37
37
  process.exit(0);
38
38
  }
39
39
 
40
- // Use the same toolchain the driver will: a bundled clang when present, with its
41
- // `LD_LIBRARY_PATH` (the legacy `libtinfo.so.5` on Linux) threaded through.
40
+ // Use the same toolchain the driver will.
42
41
  const toolchain = resolveToolchain();
43
42
  const clang = toolchain.clang;
44
43
  const childEnv = Object.assign({}, process.env, toolchain.env);
@@ -54,7 +53,7 @@ function findArchiver(clangPath: string): string {
54
53
  const exe = process.platform === "win32" ? ".exe" : "";
55
54
  const candidates = [
56
55
  process.env.xbintsc_AR,
57
- // A bundled toolchain ships `llvm-ar` next to clang.
56
+ // A clang install usually ships `llvm-ar` next to the driver.
58
57
  dir === "." ? undefined : join(dir, `llvm-ar${exe}`),
59
58
  "llvm-ar",
60
59
  "ar",
@@ -160,9 +160,9 @@ function runs(command: string): boolean {
160
160
 
161
161
  /**
162
162
  * Locate the LLVM tool `name` (`llvm-profdata`/`llvm-cov`) that matches the
163
- * clang the driver resolved. The bundled toolchains ship the tools next to
164
- * clang and cover the versioned system installs, so search there first: mixing
165
- * versions makes `llvm-profdata` reject the profile format.
163
+ * clang the driver resolved. Prefer the tool next to clang, then the
164
+ * version-suffixed system installs: mixing versions makes `llvm-profdata`
165
+ * reject the profile format.
166
166
  */
167
167
  function findTool(clang: string, name: string): string | undefined {
168
168
  const exe = process.platform === "win32" ? ".exe" : "";
@@ -282,7 +282,7 @@ function main(): void {
282
282
  profdataTool ? undefined : "llvm-profdata",
283
283
  covTool ? undefined : "llvm-cov",
284
284
  ].filter(Boolean).join(", ");
285
- skip(`${missing} not found for ${clang}; install LLVM or use the bundled toolchain`, options.strict);
285
+ skip(`${missing} not found for ${clang}; install the LLVM tools (llvm-profdata, llvm-cov)`, options.strict);
286
286
  }
287
287
 
288
288
  if (!options.reportOnly) runTests(options);
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * Assemble a self-contained release archive for the current platform:
3
+ * Assemble a release archive for the current platform:
4
4
  *
5
5
  * dist/release/xbintsc-<version>-<os>-<arch>.tar.gz (or .tar.zst)
6
6
  * dist/release/xbintsc-<version>-<os>-<arch>.tar.gz.sha256
@@ -10,23 +10,24 @@
10
10
  *
11
11
  * The unpacked staging tree is built under `build/release-stage/`, never under
12
12
  * `dist/release/`, so an upload glob over `dist/release/*` cannot accidentally
13
- * ship the (multi-GB) tree alongside the archive.
13
+ * ship the (large) tree alongside the archive.
14
+ *
15
+ * xbintsc does not bundle a compiler: the archive holds only the self-hosted
16
+ * binary and the C runtime sources plus prebuilt archives. Users provide the
17
+ * toolchain themselves (see `doc/requirements.md`).
14
18
  *
15
19
  * Layout inside the archive:
16
20
  *
17
21
  * xbintsc-<os>-<arch>/
18
22
  * bin/xbintsc[.exe] the self-hosted compiler
19
23
  * runtime/ C runtime sources + prebuilt runtime/lib/<slug>
20
- * vendor/<slug>/ the bundled clang+lld toolchain (Linux/Windows)
21
24
  * README.md
22
25
  *
23
- * The compiler locates `runtime/` and `vendor/` relative to its own executable
24
- * (see `findRuntimeDir`/`findVendorDir`), so this tree runs with no system
25
- * toolchain installed.
26
+ * The compiler locates `runtime/` relative to its own executable (see
27
+ * `findRuntimeDir`), so this tree runs without any bundled toolchain.
26
28
  *
27
29
  * Inputs:
28
30
  * - the self-hosted binary staged at `dist/xbintsc[.exe]` (CI copies it there)
29
- * - `vendor/<slug>/`, fetched by `scripts/fetch-toolchain.ts`
30
31
  * - `runtime/lib/<slug>/`, built by `scripts/build-runtime.ts`
31
32
  */
32
33
 
@@ -37,9 +38,7 @@ import {
37
38
  chmodSync,
38
39
  existsSync,
39
40
  mkdirSync,
40
- readdirSync,
41
41
  readFileSync,
42
- realpathSync,
43
42
  rmSync,
44
43
  statSync,
45
44
  writeFileSync,
@@ -49,14 +48,12 @@ import { basename, dirname, join, resolve } from "node:path";
49
48
  import { fileURLToPath } from "node:url";
50
49
  import {
51
50
  findRuntimeDir,
52
- platformSlug,
53
51
  releaseArchiveBase,
54
52
  releaseArchiveExtension,
55
53
  releaseArchiveFileName,
56
54
  } from "../src/driver/paths.js";
57
55
 
58
56
  const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
59
- const slug = platformSlug();
60
57
  const base = releaseArchiveBase();
61
58
  const version = (
62
59
  JSON.parse(readFileSync(join(root, "package.json"), "utf8")) as { version: string }
@@ -77,55 +74,6 @@ function firstExisting(candidates: readonly string[]): string | undefined {
77
74
  return undefined;
78
75
  }
79
76
 
80
- /**
81
- * Copy only the parts of the fetched toolchain that xbintsc actually runs.
82
- *
83
- * The official LLVM release unpacks to ~7 GB: every MLIR/Flang/lldb tool, the
84
- * static archives and the full C++ headers. The compiler only shells out to the
85
- * clang driver, the lld linker and llvm-ar, and clang additionally needs its own
86
- * resource directory (`lib/clang/<version>`, the builtin headers and
87
- * compiler-rt). Copying just those keeps the archive ~100x smaller.
88
- */
89
- function stageToolchain(vendor: string, dest: string): void {
90
- const exe = process.platform === "win32" ? ".exe" : "";
91
- mkdirSync(join(dest, "bin"), { recursive: true });
92
-
93
- const real = (...candidates: readonly string[]): string | undefined => {
94
- const found = firstExisting(candidates.map((candidate) => join(vendor, candidate)));
95
- return found ? realpathSync(found) : undefined;
96
- };
97
- const copyAs = (source: string | undefined, name: string): void => {
98
- if (!source) return;
99
- const target = join(dest, "bin", name);
100
- copyFileSync(source, target);
101
- if (process.platform !== "win32") chmodSync(target, 0o755);
102
- };
103
-
104
- // In the official release `clang`/`ld.lld` are symlinks into the bin/ dir;
105
- // copy the resolved targets under the names the toolchain provider (and
106
- // clang's `-fuse-ld=lld`) expect next to `bin/clang`.
107
- copyAs(real(`bin/clang${exe}`, `bin/clang-18${exe}`), `clang${exe}`);
108
- copyAs(real(`bin/ld.lld${exe}`, `bin/lld${exe}`), `ld.lld${exe}`);
109
- copyAs(real(`bin/llvm-ar${exe}`, "bin/llvm-ar"), `llvm-ar${exe}`);
110
-
111
- // clang's resource directory: builtin headers + compiler-rt archives.
112
- const resourceDir = join(vendor, "lib", "clang");
113
- if (existsSync(resourceDir)) {
114
- cpSync(resourceDir, join(dest, "lib", "clang"), { recursive: true });
115
- }
116
-
117
- // Shared libraries the fetch placed next to the toolchain (on Linux that is
118
- // the legacy `libtinfo.so.5` the official build still links).
119
- const libDir = join(vendor, "lib");
120
- if (existsSync(libDir)) {
121
- for (const entry of readdirSync(libDir, { withFileTypes: true })) {
122
- if (/^(.*\.so(\.\d+)*|.*\.dylib|.*\.dll)$/.test(entry.name)) {
123
- cpSync(join(libDir, entry.name), join(dest, "lib", entry.name), { recursive: true });
124
- }
125
- }
126
- }
127
- }
128
-
129
77
  const distDir = join(root, "dist");
130
78
  const binary = firstExisting([
131
79
  join(distDir, `xbintsc${exeSuffix}`),
@@ -138,7 +86,7 @@ if (!binary) {
138
86
 
139
87
  // Archives go to `dist/release/`; the unpacked staging tree goes to
140
88
  // `build/release-stage/` so the upload glob over `dist/release/*` cannot pick up
141
- // the raw tree (which would ship the toolchain twice, and uncompressed).
89
+ // the raw tree.
142
90
  const releaseRoot = join(distDir, "release");
143
91
  const stageRoot = join(root, "build", "release-stage");
144
92
  const stage = join(stageRoot, base);
@@ -156,33 +104,13 @@ console.log(`xbintsc: packaged binary ${basename(binary)} (${statSync(binary).si
156
104
  cpSync(findRuntimeDir(), join(stage, "runtime"), { recursive: true });
157
105
  console.log("xbintsc: packaged runtime/");
158
106
 
159
- // 3. The bundled toolchain, when one was fetched for this platform.
160
- const vendor = join(root, "vendor", slug);
161
- if (existsSync(join(vendor, "bin"))) {
162
- if (process.platform === "win32") {
163
- // llvm-mingw spreads its MinGW-w64 CRT/import libraries across the tree, so
164
- // bundling it whole is the safe default there for now.
165
- cpSync(vendor, join(stage, "vendor", slug), { recursive: true });
166
- } else {
167
- stageToolchain(vendor, join(stage, "vendor", slug));
168
- }
169
- console.log(`xbintsc: packaged vendor/${slug}/`);
170
- } else if (process.platform === "linux" || process.platform === "win32") {
171
- console.warn(
172
- `xbintsc: warning: no vendor/${slug}/ found; the release will rely on a system toolchain. ` +
173
- "Run `npm run fetch-toolchain` first for a self-contained archive.",
174
- );
175
- } else {
176
- console.log(`xbintsc: no bundled toolchain for ${slug}; relying on the system SDK (macOS)`);
177
- }
178
-
179
- // 4. Human-facing notes.
107
+ // 3. Human-facing notes.
180
108
  for (const name of ["README.md", "LICENSE"]) {
181
109
  const source = join(root, name);
182
110
  if (existsSync(source)) copyFileSync(source, join(stage, name));
183
111
  }
184
112
 
185
- // 5. Archive it. Prefer zstd when available, otherwise gzip.
113
+ // 4. Archive it. Prefer zstd when available, otherwise gzip.
186
114
  const hasZstd = !spawnSync("zstd", ["--version"], { stdio: "ignore" }).error;
187
115
  const extension = releaseArchiveExtension(hasZstd);
188
116
  const archive = join(releaseRoot, `${archiveBase}${extension}`);
@@ -192,7 +120,7 @@ const tar = spawnSync("tar", tarArgs, { stdio: "inherit" });
192
120
  if (tar.error) fail(`failed to run tar: ${tar.error.message}`);
193
121
  if (tar.status !== 0) fail(`tar exited with ${tar.status}`);
194
122
 
195
- // 6. Checksum, so users can verify the download.
123
+ // 5. Checksum, so users can verify the download.
196
124
  const digest = createHash("sha256").update(readFileSync(archive)).digest("hex");
197
125
  writeFileSync(`${archive}.sha256`, `${digest} ${basename(archive)}\n`);
198
126
 
package/src/cli/main.ts CHANGED
@@ -24,7 +24,6 @@ import { resolveToolchain } from "../driver/toolchain-provider.js";
24
24
  import { realRunner } from "../driver/toolchain.js";
25
25
  import { createDefaultRegistry, type ExtensionRegistry } from "../extensions/registry.js";
26
26
  import { bundledExtensions } from "../extensions/catalog.js";
27
- import { nodeExtension } from "../extensions/node/index.js";
28
27
  import { nativeExtensionFromManifest } from "../extensions/native.js";
29
28
 
30
29
  export interface CliIo {
@@ -100,9 +99,11 @@ function buildRegistry(flags: Map<string, string | boolean>): ExtensionRegistry
100
99
  const registry = createDefaultRegistry();
101
100
  const requested = flags.get("ext");
102
101
  if (typeof requested === "string") {
102
+ const bundled = bundledExtensions();
103
103
  for (const name of requested.split(",").map((n) => n.trim()).filter(Boolean)) {
104
- if (name === "node") registry.register(nodeExtension);
105
- else throw new Error(`Unknown extension '${name}'`);
104
+ const extension = bundled.find((candidate) => candidate.name === name);
105
+ if (!extension) throw new Error(`Unknown extension '${name}'`);
106
+ registry.register(extension);
106
107
  }
107
108
  }
108
109
  // Each `--ext-native` value is a manifest path describing a pre-built C++ or
@@ -172,7 +173,10 @@ function doctor(io: CliIo): number {
172
173
  io.stdout(`toolchain : ${toolchain.clang} (${toolchain.source})\n`);
173
174
  io.stdout(`compiler : ${firstLine(version) || "unknown"}\n`);
174
175
  } catch {
175
- io.stdout("toolchain : not found (install the Xcode Command Line Tools or set xbintsc_CLANG)\n");
176
+ io.stdout("toolchain : not found\n");
177
+ io.stdout(" install one of: Xcode Command Line Tools (`xcode-select --install`) on macOS,\n");
178
+ io.stdout(" clang+lld (apt/dnf/pacman) on Linux, or LLVM + Visual Studio C++ build tools on Windows,\n");
179
+ io.stdout(" then re-run; or set xbintsc_CLANG to a clang binary. See doc/requirements.md.\n");
176
180
  }
177
181
 
178
182
  try {
@@ -215,6 +215,10 @@ export const RUNTIME_DECLARATIONS: readonly string[] = [
215
215
  "declare i64 @xt_decode_uri(i32, i64*)",
216
216
  "declare i64 @xt_btoa(i32, i64*)",
217
217
  "declare i64 @xt_atob(i32, i64*)",
218
+ "declare i64 @xt_set_timeout(i32, i64*)",
219
+ "declare i64 @xt_clear_timeout(i32, i64*)",
220
+ "declare i64 @xt_set_interval(i32, i64*)",
221
+ "declare i64 @xt_clear_interval(i32, i64*)",
218
222
  "declare i64 @xt_number_ctor(i32, i64*)",
219
223
  "declare i64 @xt_bigint_ctor(i32, i64*)",
220
224
  "declare i64 @xt_bigint_static(i64, i32, i64*)",
@@ -246,6 +250,10 @@ export const RUNTIME_DECLARATIONS: readonly string[] = [
246
250
  "declare i64 @xt_builtin_value_encodeURI(i64, i64, i32, i64*)",
247
251
  "declare i64 @xt_builtin_value_decodeURIComponent(i64, i64, i32, i64*)",
248
252
  "declare i64 @xt_builtin_value_decodeURI(i64, i64, i32, i64*)",
253
+ "declare i64 @xt_builtin_value_setTimeout(i64, i64, i32, i64*)",
254
+ "declare i64 @xt_builtin_value_clearTimeout(i64, i64, i32, i64*)",
255
+ "declare i64 @xt_builtin_value_setInterval(i64, i64, i32, i64*)",
256
+ "declare i64 @xt_builtin_value_clearInterval(i64, i64, i32, i64*)",
249
257
  "declare i64 @xt_builtin_value_number(i64, i64, i32, i64*)",
250
258
  "declare i64 @xt_builtin_value_string(i64, i64, i32, i64*)",
251
259
  "declare i64 @xt_builtin_value_boolean(i64, i64, i32, i64*)",
@@ -12,12 +12,11 @@ import {
12
12
  /**
13
13
  * True when a `try` frame must be saved with `_setjmpex` rather than `_setjmp`.
14
14
  *
15
- * 64-bit Windows on ARM has no `_setjmp`: both the UCRT and MinGW-w64 declare
16
- * `setjmp` as `_setjmpex(buf, sponentry)` there, so the linker expects
17
- * `_setjmpex` (with the caller's stack pointer at entry, `llvm.sponentry`,
18
- * instead of its frame pointer). clang lowers a C `setjmp` on this target to
19
- * exactly that pair. Checked at code-generation time because xbintsc builds for
20
- * its own host.
15
+ * 64-bit Windows on ARM has no `_setjmp`: the UCRT declares `setjmp` as
16
+ * `_setjmpex(buf, sponentry)` there, so the linker expects `_setjmpex` (with the
17
+ * caller's stack pointer at entry, `llvm.sponentry`, instead of its frame
18
+ * pointer). clang lowers a C `setjmp` on this target to exactly that pair.
19
+ * Checked at code-generation time because xbintsc builds for its own host.
21
20
  */
22
21
  export function requiresSetjmpex(platform: string, arch: string): boolean {
23
22
  return platform === "win32" && arch === "arm64";
@@ -124,6 +123,10 @@ export const GLOBAL_FUNCTIONS: Record<string, string> = {
124
123
  decodeURI: "xt_decode_uri",
125
124
  btoa: "xt_btoa",
126
125
  atob: "xt_atob",
126
+ setTimeout: "xt_set_timeout",
127
+ clearTimeout: "xt_clear_timeout",
128
+ setInterval: "xt_set_interval",
129
+ clearInterval: "xt_clear_interval",
127
130
  Number: "xt_number_ctor",
128
131
  String: "xt_string_ctor",
129
132
  Boolean: "xt_boolean_ctor",
@@ -143,6 +146,10 @@ export const BUILTIN_FUNCTION_VALUES: Record<string, string> = {
143
146
  encodeURI: "xt_builtin_value_encodeURI",
144
147
  decodeURIComponent: "xt_builtin_value_decodeURIComponent",
145
148
  decodeURI: "xt_builtin_value_decodeURI",
149
+ setTimeout: "xt_builtin_value_setTimeout",
150
+ clearTimeout: "xt_builtin_value_clearTimeout",
151
+ setInterval: "xt_builtin_value_setInterval",
152
+ clearInterval: "xt_builtin_value_clearInterval",
146
153
  Number: "xt_builtin_value_number",
147
154
  String: "xt_builtin_value_string",
148
155
  Boolean: "xt_builtin_value_boolean",