@mnemonik/shared 7.144.1 → 7.145.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/dist/ast/grammars.d.ts +6 -6
- package/dist/ast/grammars.d.ts.map +1 -1
- package/dist/ast/grammars.js +51 -10
- package/dist/ast/grammars.js.map +1 -1
- package/dist/sourceRedaction.d.ts.map +1 -1
- package/dist/sourceRedaction.js +743 -64
- package/dist/sourceRedaction.js.map +1 -1
- package/package.json +2 -1
- package/queries/clojure.tags.scm +1 -0
- package/queries/dart.tags.scm +3 -0
- package/queries/erlang.tags.scm +2 -0
- package/queries/graphql.tags.scm +3 -0
- package/queries/haskell.tags.scm +3 -0
- package/queries/julia.tags.scm +1 -0
- package/queries/kotlin.tags.scm +3 -0
- package/queries/ocaml.tags.scm +2 -0
- package/queries/ocaml_interface.tags.scm +1 -0
- package/queries/perl.tags.scm +2 -0
- package/queries/protobuf.tags.scm +5 -0
- package/queries/r.tags.scm +2 -0
- package/queries/zig.tags.scm +2 -0
- package/scripts/vendor-grammars.ts +568 -36
- package/src/ast/grammars.ts +51 -10
- package/src/sourceRedaction.ts +765 -12
- package/wasm/bash.wasm.gz +0 -0
- package/wasm/c-sharp.wasm.gz +0 -0
- package/wasm/c.wasm.gz +0 -0
- package/wasm/clojure.LICENSE +21 -0
- package/wasm/clojure.tags.scm +1 -0
- package/wasm/clojure.wasm.gz +0 -0
- package/wasm/cmake.wasm.gz +0 -0
- package/wasm/cpp.wasm.gz +0 -0
- package/wasm/dart.LICENSE +20 -0
- package/wasm/dart.tags.scm +3 -0
- package/wasm/dart.wasm.gz +0 -0
- package/wasm/elixir.wasm.gz +0 -0
- package/wasm/erlang.LICENSE +201 -0
- package/wasm/erlang.tags.scm +2 -0
- package/wasm/erlang.wasm.gz +0 -0
- package/wasm/go.wasm.gz +0 -0
- package/wasm/graphql.LICENSE +21 -0
- package/wasm/graphql.tags.scm +3 -0
- package/wasm/graphql.wasm.gz +0 -0
- package/wasm/groovy.wasm.gz +0 -0
- package/wasm/haskell.LICENSE +21 -0
- package/wasm/haskell.tags.scm +3 -0
- package/wasm/haskell.wasm.gz +0 -0
- package/wasm/java.wasm.gz +0 -0
- package/wasm/javascript.wasm.gz +0 -0
- package/wasm/julia.LICENSE +21 -0
- package/wasm/julia.tags.scm +1 -0
- package/wasm/julia.wasm.gz +0 -0
- package/wasm/kotlin.LICENSE +9 -0
- package/wasm/kotlin.tags.scm +3 -0
- package/wasm/kotlin.wasm.gz +0 -0
- package/wasm/lua.wasm.gz +0 -0
- package/wasm/nix.wasm.gz +0 -0
- package/wasm/objcpp.wasm.gz +0 -0
- package/wasm/ocaml.LICENSE +21 -0
- package/wasm/ocaml.tags.scm +2 -0
- package/wasm/ocaml.wasm.gz +0 -0
- package/wasm/ocaml_interface.LICENSE +21 -0
- package/wasm/ocaml_interface.tags.scm +1 -0
- package/wasm/ocaml_interface.wasm.gz +0 -0
- package/wasm/perl.LICENSE +7 -0
- package/wasm/perl.tags.scm +2 -0
- package/wasm/perl.wasm.gz +0 -0
- package/wasm/php.wasm.gz +0 -0
- package/wasm/powershell.wasm.gz +0 -0
- package/wasm/protobuf.LICENSE +21 -0
- package/wasm/protobuf.tags.scm +5 -0
- package/wasm/protobuf.wasm.gz +0 -0
- package/wasm/python.wasm.gz +0 -0
- package/wasm/r.LICENSE +9 -0
- package/wasm/r.tags.scm +2 -0
- package/wasm/r.wasm.gz +0 -0
- package/wasm/ruby.wasm.gz +0 -0
- package/wasm/rust.wasm.gz +0 -0
- package/wasm/scala.wasm.gz +0 -0
- package/wasm/solidity.wasm.gz +0 -0
- package/wasm/sql.wasm.gz +0 -0
- package/wasm/swift.wasm.gz +0 -0
- package/wasm/terraform.wasm.gz +0 -0
- package/wasm/tsx.wasm.gz +0 -0
- package/wasm/typescript.wasm.gz +0 -0
- package/wasm/zig.LICENSE +29 -0
- package/wasm/zig.tags.scm +2 -0
- package/wasm/zig.wasm.gz +0 -0
- package/wasm/bash.wasm +0 -0
- package/wasm/c-sharp.wasm +0 -0
- package/wasm/c.wasm +0 -0
- package/wasm/cmake.wasm +0 -0
- package/wasm/cpp.wasm +0 -0
- package/wasm/elixir.wasm +0 -0
- package/wasm/go.wasm +0 -0
- package/wasm/groovy.wasm +0 -0
- package/wasm/java.wasm +0 -0
- package/wasm/javascript.wasm +0 -0
- package/wasm/lua.wasm +0 -0
- package/wasm/nix.wasm +0 -0
- package/wasm/objcpp.wasm +0 -0
- package/wasm/php.wasm +0 -0
- package/wasm/powershell.wasm +0 -0
- package/wasm/python.wasm +0 -0
- package/wasm/ruby.wasm +0 -0
- package/wasm/rust.wasm +0 -0
- package/wasm/scala.wasm +0 -0
- package/wasm/solidity.wasm +0 -0
- package/wasm/sql.wasm +0 -0
- package/wasm/swift.wasm +0 -0
- package/wasm/terraform.wasm +0 -0
- package/wasm/tsx.wasm +0 -0
- package/wasm/typescript.wasm +0 -0
|
@@ -11,13 +11,13 @@
|
|
|
11
11
|
* so there is no peer graph to satisfy, `npm ci` stays fast for every developer
|
|
12
12
|
* and every CI run, and nobody downloads ~283 MB of grammars to build the repo.
|
|
13
13
|
*
|
|
14
|
-
* What ships to a user:
|
|
14
|
+
* What ships to a user: deterministic `.wasm.gz` and `.tags.scm` files, committed
|
|
15
15
|
* here and published inside @mnemonik/shared. A user's install therefore pulls
|
|
16
16
|
* no grammar package, runs no postinstall, needs no compiler, and fetches
|
|
17
17
|
* nothing at runtime - which is the whole reason this plan chose WebAssembly
|
|
18
18
|
* over the native bindings.
|
|
19
19
|
*
|
|
20
|
-
* Run: npx tsx packages/shared/scripts/vendor-grammars.ts [--check | --only=<id>]
|
|
20
|
+
* Run: npx tsx packages/shared/scripts/vendor-grammars.ts [--check | --only=<id>[,<id>...]]
|
|
21
21
|
* JSX repair: run --only=javascript and --only=tsx; other assets stay untouched.
|
|
22
22
|
* --check verify every manifest entry is present and non-empty; write nothing.
|
|
23
23
|
* This is what CI should run to catch a grammar that silently stopped
|
|
@@ -40,6 +40,7 @@ import {
|
|
|
40
40
|
import { tmpdir } from 'node:os';
|
|
41
41
|
import { basename, join } from 'node:path';
|
|
42
42
|
import { fileURLToPath } from 'node:url';
|
|
43
|
+
import { gzipSync, gunzipSync } from 'node:zlib';
|
|
43
44
|
import { Language, Parser, Query } from 'web-tree-sitter';
|
|
44
45
|
import { AST_LANGUAGE_IDS, QUERY_CHAIN, grammarArtifactBasename } from '../src/ast/grammars.js';
|
|
45
46
|
|
|
@@ -64,6 +65,10 @@ interface GrammarSpec {
|
|
|
64
65
|
* maintain when the upstream query is absent or captures unsuitable ranges.
|
|
65
66
|
*/
|
|
66
67
|
tags: 'upstream' | 'ours' | 'inherited';
|
|
68
|
+
/** Compile committed source, regenerating only obsolete parser ABIs. */
|
|
69
|
+
build?: 'source' | 'regenerate';
|
|
70
|
+
/** Copy the source license alongside new grammar artifacts. */
|
|
71
|
+
licenseFile?: string;
|
|
67
72
|
}
|
|
68
73
|
|
|
69
74
|
/**
|
|
@@ -72,23 +77,103 @@ interface GrammarSpec {
|
|
|
72
77
|
* and losing a language is exactly the silent degradation this plan exists to
|
|
73
78
|
* remove.
|
|
74
79
|
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
* costs both its size (6.1/3.7 MB) and a hand-written query. Dropped to
|
|
78
|
-
* bound the payload; still indexed via the
|
|
79
|
-
* allowlist, still chunked heuristically.
|
|
80
|
-
* dart - its bundled .wasm (package v1.0.0, 2023) fails Language.load under
|
|
81
|
-
* web-tree-sitter 0.26.11 with a dylink-metadata error: the artifact
|
|
82
|
-
* predates the current wasm ABI. Presence is not loadability, which is why
|
|
83
|
-
* --check verifies both. Flutter matters, so this is worth revisiting by
|
|
84
|
-
* compiling from source with tree-sitter-cli.
|
|
85
|
-
* kotlin, perl, zig - bundle no .wasm, so they need a build step
|
|
86
|
-
* with tree-sitter-cli. Deferred until the grammars above are proven; they
|
|
87
|
-
* keep the heuristic chunker meanwhile.
|
|
88
|
-
* markdown - keeps chunkMarkdown. Headers already are a document's semantic
|
|
89
|
-
* unit; an AST would not improve on them.
|
|
80
|
+
* Markdown retains its document-header chunker. Svelte component parsing is
|
|
81
|
+
* owned by its adapter; it does not need another tree-sitter WASM.
|
|
90
82
|
*/
|
|
91
83
|
const GRAMMARS: GrammarSpec[] = [
|
|
84
|
+
// fwcd MIT 0.3.8, e1a2d5ad1f61f5740677183cd4125bb071cd2f30, ABI 14.
|
|
85
|
+
{
|
|
86
|
+
id: 'kotlin',
|
|
87
|
+
pkg: 'tree-sitter-kotlin@0.3.8',
|
|
88
|
+
tags: 'ours',
|
|
89
|
+
build: 'source',
|
|
90
|
+
licenseFile: 'LICENSE',
|
|
91
|
+
},
|
|
92
|
+
// UserNobody14 ISC 1.0.0, 53485a8f301254e19c518aa20c80f1bcf7cf5c62.
|
|
93
|
+
// Rebuild ABI-14 source: its published WASM has obsolete dynamic-link metadata.
|
|
94
|
+
{
|
|
95
|
+
id: 'dart',
|
|
96
|
+
pkg: 'tree-sitter-dart@1.0.0',
|
|
97
|
+
tags: 'ours',
|
|
98
|
+
build: 'source',
|
|
99
|
+
licenseFile: 'LICENSE',
|
|
100
|
+
},
|
|
101
|
+
// WhatsApp Apache-2.0, committed ABI 15. The unscoped npm name is a security holder.
|
|
102
|
+
{
|
|
103
|
+
id: 'erlang',
|
|
104
|
+
pkg: 'https://codeload.github.com/WhatsApp/tree-sitter-erlang/tar.gz/62c82e67b73e13f3ef06e4c8c07ff035a8235d30',
|
|
105
|
+
tags: 'ours',
|
|
106
|
+
build: 'source',
|
|
107
|
+
licenseFile: 'LICENSE',
|
|
108
|
+
},
|
|
109
|
+
// MIT 0.23.1, c30d812bc90827f1a54106a25bc9a6307f5cdcec, packaged ABI 14.
|
|
110
|
+
{ id: 'haskell', pkg: 'tree-sitter-haskell@0.23.1', tags: 'ours', licenseFile: 'LICENSE' },
|
|
111
|
+
// MIT 0.24.2, 0cc270ff90ca09c29d0f2f9dec69ddfef55a3eff, packaged ABI 14.
|
|
112
|
+
{
|
|
113
|
+
id: 'ocaml',
|
|
114
|
+
pkg: 'tree-sitter-ocaml@0.24.2',
|
|
115
|
+
wasmFile: 'tree-sitter-ocaml.wasm',
|
|
116
|
+
tags: 'ours',
|
|
117
|
+
licenseFile: 'LICENSE',
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
id: 'ocaml_interface',
|
|
121
|
+
pkg: 'tree-sitter-ocaml@0.24.2',
|
|
122
|
+
wasmFile: 'tree-sitter-ocaml_interface.wasm',
|
|
123
|
+
tags: 'ours',
|
|
124
|
+
licenseFile: 'LICENSE',
|
|
125
|
+
},
|
|
126
|
+
// oakmac MIT 0.4.0, 290a67a3368be3847b1dd15327bd3a63f2f671ad; regenerate ABI 9.
|
|
127
|
+
{
|
|
128
|
+
id: 'clojure',
|
|
129
|
+
pkg: 'tree-sitter-clojure@0.4.0',
|
|
130
|
+
tags: 'ours',
|
|
131
|
+
build: 'regenerate',
|
|
132
|
+
licenseFile: 'LICENSE.md',
|
|
133
|
+
},
|
|
134
|
+
// MIT 0.23.1, a8e1262997d5a45520a06cbe1b86c0737d507054, packaged ABI 14.
|
|
135
|
+
{ id: 'julia', pkg: 'tree-sitter-julia@0.23.1', tags: 'ours', licenseFile: 'LICENSE' },
|
|
136
|
+
// MIT 2.0.0, 50904961d6a87c5191e611276aa2ecb9d66ca4ff, committed ABI 15.
|
|
137
|
+
{
|
|
138
|
+
id: 'perl',
|
|
139
|
+
pkg: 'tree-sitter-perl@2.0.0',
|
|
140
|
+
tags: 'ours',
|
|
141
|
+
build: 'source',
|
|
142
|
+
licenseFile: 'LICENSE',
|
|
143
|
+
},
|
|
144
|
+
// r-lib MIT 1.3.0, committed ABI 14. The unscoped npm name is a security holder.
|
|
145
|
+
{
|
|
146
|
+
id: 'r',
|
|
147
|
+
pkg: 'https://codeload.github.com/r-lib/tree-sitter-r/tar.gz/58a22794466c0fc15b0d3b40531db751593721e8',
|
|
148
|
+
tags: 'ours',
|
|
149
|
+
build: 'source',
|
|
150
|
+
licenseFile: 'LICENSE',
|
|
151
|
+
},
|
|
152
|
+
// GrayJack BSD-3-Clause 0.2.0, fb8e54448f19f5d78d7cdc664b35bffa8ec48876; regenerate ABI 10.
|
|
153
|
+
{
|
|
154
|
+
id: 'zig',
|
|
155
|
+
pkg: 'tree-sitter-zig@0.2.0',
|
|
156
|
+
tags: 'ours',
|
|
157
|
+
build: 'regenerate',
|
|
158
|
+
licenseFile: 'LICENSE',
|
|
159
|
+
},
|
|
160
|
+
// treywood MIT 0.1.0, committed ABI 14; verified upstream source and license.
|
|
161
|
+
{
|
|
162
|
+
id: 'protobuf',
|
|
163
|
+
pkg: 'https://codeload.github.com/treywood/tree-sitter-proto/tar.gz/e9f6b43f6844bd2189b50a422d4e2094313f6aa3',
|
|
164
|
+
wasmFile: 'tree-sitter-proto.wasm',
|
|
165
|
+
tags: 'ours',
|
|
166
|
+
build: 'source',
|
|
167
|
+
licenseFile: 'LICENSE',
|
|
168
|
+
},
|
|
169
|
+
// bkegley MIT 0.0.1, committed ABI 13; avoid the unrelated ISC npm package.
|
|
170
|
+
{
|
|
171
|
+
id: 'graphql',
|
|
172
|
+
pkg: 'https://codeload.github.com/bkegley/tree-sitter-graphql/tar.gz/5e66e961eee421786bdda8495ed1db045e06b5fe',
|
|
173
|
+
tags: 'ours',
|
|
174
|
+
build: 'regenerate',
|
|
175
|
+
licenseFile: 'LICENSE',
|
|
176
|
+
},
|
|
92
177
|
{
|
|
93
178
|
// Uy Ha 0.7.5, MIT; build the committed ABI-14 source without native dependencies.
|
|
94
179
|
id: 'cmake',
|
|
@@ -123,7 +208,7 @@ const GRAMMARS: GrammarSpec[] = [
|
|
|
123
208
|
// MIT 0.23.4, gitHead f41e1a044c8a84ea9fa8577fdd2eab92ec96de02.
|
|
124
209
|
{ id: 'cpp', pkg: 'tree-sitter-cpp@0.23.4', tags: 'upstream' },
|
|
125
210
|
{
|
|
126
|
-
// MIT Objective-C++ 0.1.0;
|
|
211
|
+
// MIT Objective-C++ 0.1.0; pinned source, not the pure Objective-C npm grammar.
|
|
127
212
|
id: 'objcpp',
|
|
128
213
|
pkg: 'https://tangled.org/dunkirk.sh/dots',
|
|
129
214
|
wasmFile: 'tree-sitter-objcpp.wasm',
|
|
@@ -215,7 +300,7 @@ async function checkOnly(): Promise<Problem[]> {
|
|
|
215
300
|
await Parser.init();
|
|
216
301
|
|
|
217
302
|
for (const spec of GRAMMARS) {
|
|
218
|
-
const wasm = join(WASM_DIR, `${spec.id}.wasm`);
|
|
303
|
+
const wasm = join(WASM_DIR, `${spec.id}.wasm.gz`);
|
|
219
304
|
if (!existsSync(wasm) || statSync(wasm).size === 0) {
|
|
220
305
|
problems.push({ id: spec.id, detail: `missing or empty ${spec.id}.wasm` });
|
|
221
306
|
continue;
|
|
@@ -223,7 +308,7 @@ async function checkOnly(): Promise<Problem[]> {
|
|
|
223
308
|
|
|
224
309
|
let language: Language;
|
|
225
310
|
try {
|
|
226
|
-
language = await Language.load(wasm);
|
|
311
|
+
language = await Language.load(gunzipSync(readFileSync(wasm)));
|
|
227
312
|
} catch (err) {
|
|
228
313
|
problems.push({
|
|
229
314
|
id: spec.id,
|
|
@@ -277,9 +362,9 @@ async function checkOnly(): Promise<Problem[]> {
|
|
|
277
362
|
}
|
|
278
363
|
|
|
279
364
|
/**
|
|
280
|
-
*
|
|
281
|
-
* Keep
|
|
282
|
-
*
|
|
365
|
+
* Repair demonstrated syntax omissions in pinned 0.23.2 without changing source positions.
|
|
366
|
+
* Keep contextual names and type-only forms distinct from runtime calls; retain
|
|
367
|
+
* expression ambiguity through explicit GLR conflicts instead of guessing.
|
|
283
368
|
* Source: https://github.com/tree-sitter/tree-sitter-typescript/tree/v0.23.2
|
|
284
369
|
* MIT; CLI 0.24.4 uses emscripten/emsdk:3.1.64 for the WASM build.
|
|
285
370
|
*/
|
|
@@ -289,12 +374,40 @@ function rebuildTypescript(dir: string, work: string, only?: string): void {
|
|
|
289
374
|
for (const [before, after] of [
|
|
290
375
|
[
|
|
291
376
|
' _reserved_identifier: (_, previous) => choice(',
|
|
292
|
-
" _reserved_identifier: (_, previous) => choice(\n 'unique',",
|
|
377
|
+
" _reserved_identifier: (_, previous) => choice(\n 'unique',\n 'as',",
|
|
293
378
|
],
|
|
294
379
|
[' [$.call_expression, $._type_query_call_expression],\n', ''],
|
|
295
380
|
[
|
|
296
381
|
' conflicts: ($, previous) => previous.concat([',
|
|
297
|
-
' conflicts: ($, previous) => previous.concat([\n [$.call_expression, $._type_query_call_expression],',
|
|
382
|
+
' conflicts: ($, previous) => previous.concat([\n [$.call_expression, $._type_query_call_expression],\n [$.primary_expression, $.arrow_function, $.method_definition],',
|
|
383
|
+
],
|
|
384
|
+
[
|
|
385
|
+
" field('type_arguments', optional($.type_arguments)),\n field('arguments', $.arguments),",
|
|
386
|
+
" field('type_arguments', optional($.type_arguments)),\n field('arguments', choice($.arguments, $.template_string)),",
|
|
387
|
+
],
|
|
388
|
+
[
|
|
389
|
+
" type_parameter: $ => seq(\n optional('const'),\n field('name', $._type_identifier),",
|
|
390
|
+
" type_parameter: $ => seq(\n optional(choice('const', 'in', 'out', seq('in', 'out'))),\n field('name', choice($._type_identifier, alias('out', $.type_identifier))),",
|
|
391
|
+
],
|
|
392
|
+
[
|
|
393
|
+
' $.export_clause,\n optional($._from_clause),',
|
|
394
|
+
" choice(\n seq($.export_clause, optional($._from_clause)),\n seq(choice('*', $.namespace_export), $._from_clause),\n ),",
|
|
395
|
+
],
|
|
396
|
+
[
|
|
397
|
+
" choice(',', $._semicolon),\n choice(",
|
|
398
|
+
" choice(',', $._semicolon, $._function_signature_automatic_semicolon),\n choice(",
|
|
399
|
+
],
|
|
400
|
+
[
|
|
401
|
+
" mapped_type_clause: $ => seq(\n field('name', $._type_identifier),",
|
|
402
|
+
" mapped_type_clause: $ => seq(\n field('name', choice($._type_identifier, alias('type', $.type_identifier))),",
|
|
403
|
+
],
|
|
404
|
+
[
|
|
405
|
+
' alias($._template_chars, $.string_fragment),\n $.template_type,',
|
|
406
|
+
' alias($._template_chars, $.string_fragment),\n $.escape_sequence,\n $.template_type,',
|
|
407
|
+
],
|
|
408
|
+
[
|
|
409
|
+
" field('name', choice($.identifier, $._destructuring_pattern)),",
|
|
410
|
+
" field('name', choice($.identifier, alias('as', $.identifier), $._destructuring_pattern)),",
|
|
298
411
|
],
|
|
299
412
|
] as const) {
|
|
300
413
|
if (!grammar.includes(before)) throw new Error('TypeScript grammar patch no longer applies');
|
|
@@ -329,6 +442,31 @@ function rebuildTypescript(dir: string, work: string, only?: string): void {
|
|
|
329
442
|
),`
|
|
330
443
|
);
|
|
331
444
|
writeFileSync(grammarPath, grammar);
|
|
445
|
+
const scannerPath = join(dir, 'common', 'scanner.h');
|
|
446
|
+
let scanner = readFileSync(scannerPath, 'utf8');
|
|
447
|
+
const before = " case '<':\n";
|
|
448
|
+
if (!scanner.includes(before))
|
|
449
|
+
throw new Error('TypeScript generic-overload ASI patch no longer applies');
|
|
450
|
+
scanner = scanner
|
|
451
|
+
.replace(before, '')
|
|
452
|
+
.replace(
|
|
453
|
+
" case '{':",
|
|
454
|
+
" case '<':\n // Only type-member/signature boundaries may precede a new generic overload.\n return valid_symbols[FUNCTION_SIGNATURE_AUTOMATIC_SEMICOLON] && !valid_symbols[LOGICAL_OR];\n\n case '{':"
|
|
455
|
+
);
|
|
456
|
+
const inBoundary =
|
|
457
|
+
' if (!iswalpha(lexer->lookahead)) {\n return false;\n }';
|
|
458
|
+
if (!scanner.includes(inBoundary))
|
|
459
|
+
throw new Error('TypeScript in-property ASI patch no longer applies');
|
|
460
|
+
scanner = scanner.replace(
|
|
461
|
+
inBoundary,
|
|
462
|
+
' if (!iswalpha(lexer->lookahead)) {\n return !valid_symbols[LOGICAL_OR];\n }'
|
|
463
|
+
);
|
|
464
|
+
const optionalTuple =
|
|
465
|
+
"lexer->lookahead == ':' || lexer->lookahead == ')' || lexer->lookahead == ','";
|
|
466
|
+
if (!scanner.includes(optionalTuple))
|
|
467
|
+
throw new Error('TypeScript optional-tuple patch no longer applies');
|
|
468
|
+
scanner = scanner.replace(optionalTuple, optionalTuple + " || lexer->lookahead == ']'");
|
|
469
|
+
writeFileSync(scannerPath, scanner);
|
|
332
470
|
// Retain our type/enum declaration captures when the vendor loop copies the query.
|
|
333
471
|
copyFileSync(join(WASM_DIR, 'typescript.tags.scm'), join(dir, 'queries', 'tags.scm'));
|
|
334
472
|
const tools = join(work, 'typescript-build');
|
|
@@ -344,7 +482,7 @@ function rebuildTypescript(dir: string, work: string, only?: string): void {
|
|
|
344
482
|
]);
|
|
345
483
|
const cli = join(tools, 'node_modules', '.bin', 'tree-sitter');
|
|
346
484
|
for (const dialect of ['typescript', 'tsx']) {
|
|
347
|
-
if (only && only
|
|
485
|
+
if (only && !only.split(',').includes(dialect)) continue;
|
|
348
486
|
// Apply the JSX scanner and attribute repairs only to TSX.
|
|
349
487
|
if (dialect === 'tsx') {
|
|
350
488
|
patchJsxScanner(join(dir, 'common', 'scanner.h'));
|
|
@@ -433,7 +571,23 @@ function rebuildSwift(dir: string, work: string): void {
|
|
|
433
571
|
const grammar = readFileSync(grammarPath, 'utf8');
|
|
434
572
|
const before = ' alias($._nil_coalescing_operator, "??")';
|
|
435
573
|
if (!grammar.includes(before)) throw new Error('Swift optional-marker patch no longer applies');
|
|
436
|
-
|
|
574
|
+
// Keep a conditional's braces outside nested `try await`, just as for direct calls.
|
|
575
|
+
const awaited =
|
|
576
|
+
' prec.left(0, $.call_expression),\n // Similarly special case';
|
|
577
|
+
if (!grammar.includes(awaited)) throw new Error('Swift try-await patch no longer applies');
|
|
578
|
+
const conflict = ' [$.try_expression, $._expression],';
|
|
579
|
+
if (!grammar.includes(conflict))
|
|
580
|
+
throw new Error('Swift try-await conflict patch no longer applies');
|
|
581
|
+
writeFileSync(
|
|
582
|
+
grammarPath,
|
|
583
|
+
grammar
|
|
584
|
+
.replace(before, ' token.immediate("??")')
|
|
585
|
+
.replace(
|
|
586
|
+
awaited,
|
|
587
|
+
' prec.left(0, $.call_expression),\n prec.left(0, $.await_expression),\n // Similarly special case'
|
|
588
|
+
)
|
|
589
|
+
.replace(conflict, conflict + '\n [$.try_expression, $._primary_expression],')
|
|
590
|
+
);
|
|
437
591
|
const scannerPath = join(dir, 'src', 'scanner.c');
|
|
438
592
|
const scanner = readFileSync(scannerPath, 'utf8');
|
|
439
593
|
const continuation =
|
|
@@ -497,6 +651,18 @@ function vendorObjcpp(work: string, repository: string): string {
|
|
|
497
651
|
]);
|
|
498
652
|
git(['checkout', '--quiet', '--detach', 'FETCH_HEAD']);
|
|
499
653
|
const dir = join(root, 'packages', 'tree-sitter-objcpp');
|
|
654
|
+
const grammarPath = join(dir, 'grammar.js');
|
|
655
|
+
let grammar = readFileSync(grammarPath, 'utf8');
|
|
656
|
+
const before = ' _objc_implementation_item: $ => choice(\n';
|
|
657
|
+
if (!grammar.includes(before))
|
|
658
|
+
throw new Error('Objective-C++ macro-body patch no longer applies');
|
|
659
|
+
grammar = grammar.replace(
|
|
660
|
+
before,
|
|
661
|
+
" objc_macro_body: $ => seq($.objc_macro_invocation, field('body', $.compound_statement)),\n\n" +
|
|
662
|
+
before +
|
|
663
|
+
' $.objc_macro_body,\n'
|
|
664
|
+
);
|
|
665
|
+
writeFileSync(grammarPath, grammar);
|
|
500
666
|
const tools = join(work, 'objcpp-build');
|
|
501
667
|
execFileSync('npm', [
|
|
502
668
|
'install',
|
|
@@ -506,10 +672,17 @@ function vendorObjcpp(work: string, repository: string): string {
|
|
|
506
672
|
'--no-fund',
|
|
507
673
|
'--no-package-lock',
|
|
508
674
|
'tree-sitter-cli@0.24.4',
|
|
675
|
+
// Match the pinned source's lockfile; these are grammar sources, never runtime dependencies.
|
|
676
|
+
'tree-sitter-c@0.23.6',
|
|
677
|
+
'tree-sitter-cpp@0.23.4',
|
|
509
678
|
]);
|
|
510
|
-
|
|
679
|
+
const cli = join(tools, 'node_modules', '.bin', 'tree-sitter');
|
|
680
|
+
execFileSync(cli, ['generate'], {
|
|
681
|
+
cwd: dir,
|
|
682
|
+
env: { ...process.env, NODE_PATH: join(tools, 'node_modules') },
|
|
683
|
+
});
|
|
511
684
|
execFileSync(
|
|
512
|
-
|
|
685
|
+
cli,
|
|
513
686
|
['build', '--wasm', '--docker', '--output', join(dir, 'tree-sitter-objcpp.wasm')],
|
|
514
687
|
{ cwd: dir }
|
|
515
688
|
);
|
|
@@ -595,12 +768,35 @@ function rebuildSql(dir: string, work: string): void {
|
|
|
595
768
|
$.keyword_create, make_keyword("policy"), field('name', $.identifier),
|
|
596
769
|
$.keyword_on, alias($.policy_relation, $.relation),
|
|
597
770
|
optional(seq($.keyword_for, choice($.keyword_select, $.keyword_insert, $.keyword_update, $.keyword_delete))),
|
|
598
|
-
optional(seq($.keyword_to, $.identifier)),
|
|
771
|
+
optional(seq($.keyword_to, comma_list($.identifier, true))),
|
|
599
772
|
optional(seq($.keyword_using, wrapped_in_parenthesis($._expression))),
|
|
600
773
|
optional(seq($.keyword_with, $.keyword_check, wrapped_in_parenthesis($._expression))),
|
|
601
774
|
),
|
|
602
775
|
create_table: $ => prec.left(`
|
|
603
776
|
);
|
|
777
|
+
// These stored migrations use qualified enum names and table/sequence grants.
|
|
778
|
+
patch(
|
|
779
|
+
` alter_type: $ => seq(
|
|
780
|
+
$.keyword_alter,
|
|
781
|
+
$.keyword_type,
|
|
782
|
+
$.identifier,`,
|
|
783
|
+
` alter_type: $ => seq(
|
|
784
|
+
$.keyword_alter,
|
|
785
|
+
$.keyword_type,
|
|
786
|
+
$.object_reference,`
|
|
787
|
+
);
|
|
788
|
+
patch(' $.reset_statement,', ' $.reset_statement,\n $.grant_statement,');
|
|
789
|
+
patch(
|
|
790
|
+
' _cte: $ => seq(',
|
|
791
|
+
` grant_statement: $ => seq(
|
|
792
|
+
make_keyword("grant"),
|
|
793
|
+
comma_list(choice($.keyword_select, $.keyword_insert, $.keyword_update, $.keyword_delete, make_keyword("usage")), true),
|
|
794
|
+
$.keyword_on, optional($.keyword_sequence), comma_list($.object_reference, true),
|
|
795
|
+
$.keyword_to, comma_list($.identifier, true),
|
|
796
|
+
),
|
|
797
|
+
|
|
798
|
+
_cte: $ => seq(`
|
|
799
|
+
);
|
|
604
800
|
// Dollar-quoted procedural code is one literal, never a parsed SQL statement list.
|
|
605
801
|
patch(' $.reset_statement,', ' $.reset_statement,\n $.do_statement,');
|
|
606
802
|
patch(
|
|
@@ -623,6 +819,240 @@ function rebuildSql(dir: string, work: string): void {
|
|
|
623
819
|
' conflicts: $ => [',
|
|
624
820
|
' conflicts: $ => [\n [$._expression, $._inner_default_expression],\n [$.create_function],'
|
|
625
821
|
);
|
|
822
|
+
// Fixed R2 cohort: change individual upstream rules, retaining the scanner and AST names.
|
|
823
|
+
const patchRule = (name: string, before: string, after: string): void => {
|
|
824
|
+
const start = grammar.indexOf(` ${name}:`);
|
|
825
|
+
if (start < 0) throw new Error(`SQL rule missing: ${name}`);
|
|
826
|
+
const next = grammar.slice(start + 1).search(/^ [a-zA-Z_]\w*\s*:/m);
|
|
827
|
+
const end = next < 0 ? grammar.length : start + 1 + next;
|
|
828
|
+
const rule = grammar.slice(start, end);
|
|
829
|
+
if (!rule.includes(before)) throw new Error(`SQL ${name} patch no longer applies`);
|
|
830
|
+
grammar = grammar.slice(0, start) + rule.replace(before, after) + grammar.slice(end);
|
|
831
|
+
};
|
|
832
|
+
patchRule('_type', 'prec.left(', 'prec.right(');
|
|
833
|
+
patchRule('array_size_definition', 'prec.left(', 'prec.right(');
|
|
834
|
+
patchRule(
|
|
835
|
+
'_type',
|
|
836
|
+
'$.keyword_geography,',
|
|
837
|
+
`seq($.keyword_geography, optional(wrapped_in_parenthesis(
|
|
838
|
+
seq($.identifier, optional(seq(',', $._natural_number)))
|
|
839
|
+
))),`
|
|
840
|
+
);
|
|
841
|
+
patchRule(
|
|
842
|
+
'_column_constraint',
|
|
843
|
+
'$.keyword_auto_increment,',
|
|
844
|
+
`choice($.keyword_auto_increment, make_keyword("autoincrement")),`
|
|
845
|
+
);
|
|
846
|
+
patchRule('function_argument', '$.literal,', '$._expression,');
|
|
847
|
+
patchRule(
|
|
848
|
+
'_inner_default_expression',
|
|
849
|
+
'$.keyword_current_timestamp,',
|
|
850
|
+
`$.keyword_current_timestamp,
|
|
851
|
+
make_keyword("current_date"),`
|
|
852
|
+
);
|
|
853
|
+
patchRule('create_policy', '$.keyword_delete))),', '$.keyword_delete, $.keyword_all))),');
|
|
854
|
+
patchRule(
|
|
855
|
+
'_create_statement',
|
|
856
|
+
'$.create_function,',
|
|
857
|
+
'alias($.create_procedure, $.create_function),\n $.create_function,'
|
|
858
|
+
);
|
|
859
|
+
patchRule(
|
|
860
|
+
'_drop_statement',
|
|
861
|
+
'$.drop_function,',
|
|
862
|
+
'$.drop_function,\n $.drop_procedure,\n $.drop_policy,'
|
|
863
|
+
);
|
|
864
|
+
patchRule('_alter_statement', '$.alter_type,', '$.alter_type,\n $.alter_policy,');
|
|
865
|
+
patchRule(
|
|
866
|
+
'drop_function',
|
|
867
|
+
'$.object_reference,',
|
|
868
|
+
'$.object_reference,\n optional($.function_arguments),'
|
|
869
|
+
);
|
|
870
|
+
patchRule('drop_index', 'field("name", $.identifier)', 'field("name", $.object_reference)');
|
|
871
|
+
patchRule(
|
|
872
|
+
'alter_column',
|
|
873
|
+
"field('type', $._type),",
|
|
874
|
+
"field('type', $._type),\n optional(seq($.keyword_using, $._expression)),"
|
|
875
|
+
);
|
|
876
|
+
patchRule(
|
|
877
|
+
'add_constraint',
|
|
878
|
+
'$.constraint,',
|
|
879
|
+
'$.constraint,\n optional(seq($.keyword_not, make_keyword("valid"))),'
|
|
880
|
+
);
|
|
881
|
+
patchRule(
|
|
882
|
+
'_alter_specifications',
|
|
883
|
+
'$.set_schema,',
|
|
884
|
+
`$.set_schema,
|
|
885
|
+
seq(make_keyword("validate"), $.keyword_constraint, $.identifier),
|
|
886
|
+
seq($.keyword_rename, $.keyword_constraint, $.identifier, $.keyword_to, $.identifier),
|
|
887
|
+
seq($.keyword_set, paren_list(seq($.identifier, '=', $.literal), true)),
|
|
888
|
+
seq($.keyword_reset, paren_list($.identifier, true)),`
|
|
889
|
+
);
|
|
890
|
+
patchRule(
|
|
891
|
+
'_table_settings',
|
|
892
|
+
'$.table_partition,',
|
|
893
|
+
`seq($.keyword_on, $.keyword_commit, $.keyword_drop),
|
|
894
|
+
$.table_partition,`
|
|
895
|
+
);
|
|
896
|
+
patchRule(
|
|
897
|
+
'create_index',
|
|
898
|
+
'$.index_fields',
|
|
899
|
+
`$.index_fields,
|
|
900
|
+
optional(seq(make_keyword("include"), paren_list($.identifier, true)))`
|
|
901
|
+
);
|
|
902
|
+
patchRule(
|
|
903
|
+
'transaction',
|
|
904
|
+
" optional(';'),",
|
|
905
|
+
` optional(choice(
|
|
906
|
+
seq($.keyword_read, $.keyword_only),
|
|
907
|
+
seq($.keyword_isolation, $.keyword_level, $.keyword_repeatable, $.keyword_read)
|
|
908
|
+
)),
|
|
909
|
+
optional(';'),`
|
|
910
|
+
);
|
|
911
|
+
patchRule(
|
|
912
|
+
'limit',
|
|
913
|
+
'$.literal,',
|
|
914
|
+
'choice($.literal, $.parameter, alias($._qualified_field, $.field)),'
|
|
915
|
+
);
|
|
916
|
+
patchRule(
|
|
917
|
+
'offset',
|
|
918
|
+
'$.literal,',
|
|
919
|
+
'choice($.literal, $.parameter, alias($._qualified_field, $.field)),'
|
|
920
|
+
);
|
|
921
|
+
patchRule(
|
|
922
|
+
'statement',
|
|
923
|
+
` optional($.keyword_analyze),
|
|
924
|
+
optional($.keyword_verbose),`,
|
|
925
|
+
` choice(
|
|
926
|
+
seq(optional($.keyword_analyze), optional($.keyword_verbose)),
|
|
927
|
+
paren_list(seq(choice($.identifier, $.keyword_analyze, $.keyword_verbose),
|
|
928
|
+
optional(choice($.keyword_on, $.keyword_off, $.keyword_true, $.keyword_false))), true)
|
|
929
|
+
),`
|
|
930
|
+
);
|
|
931
|
+
patchRule(
|
|
932
|
+
'_ddl_statement',
|
|
933
|
+
'$.reset_statement,',
|
|
934
|
+
`$.reset_statement,
|
|
935
|
+
$.revoke_statement,
|
|
936
|
+
$.alter_default_privileges,
|
|
937
|
+
$.analyze_statement,
|
|
938
|
+
$.lock_statement,
|
|
939
|
+
$.prepare_statement,
|
|
940
|
+
$.execute_statement,
|
|
941
|
+
$.call_statement,`
|
|
942
|
+
);
|
|
943
|
+
patchRule(
|
|
944
|
+
'_delete_from',
|
|
945
|
+
'$.object_reference,',
|
|
946
|
+
`$.object_reference,
|
|
947
|
+
optional($._alias),
|
|
948
|
+
optional(seq($.keyword_using, comma_list($.relation, true))),`
|
|
949
|
+
);
|
|
950
|
+
patchRule(
|
|
951
|
+
'cte',
|
|
952
|
+
'choice($._dml_read, $._dml_write)',
|
|
953
|
+
'choice($._dml_read, $._dml_write, $.values)'
|
|
954
|
+
);
|
|
955
|
+
patchRule(
|
|
956
|
+
'_on_conflict',
|
|
957
|
+
'optional($._column_list),',
|
|
958
|
+
'optional(seq(paren_list($._expression, true), optional($.where))),'
|
|
959
|
+
);
|
|
960
|
+
patchRule('from', `comma_list($.relation, true),`, '$.relation,');
|
|
961
|
+
patchRule(
|
|
962
|
+
'from',
|
|
963
|
+
` $.join,`,
|
|
964
|
+
` seq(',', $.relation),
|
|
965
|
+
$.join,`
|
|
966
|
+
);
|
|
967
|
+
patchRule('from', ' optional($.order_by),\n optional($.limit),', '');
|
|
968
|
+
patchRule(
|
|
969
|
+
'_select_statement',
|
|
970
|
+
' optional($.from),',
|
|
971
|
+
` optional($.from),
|
|
972
|
+
optional($.order_by),
|
|
973
|
+
optional($.limit),`
|
|
974
|
+
);
|
|
975
|
+
patchRule(
|
|
976
|
+
'set_operation',
|
|
977
|
+
` ),\n ),`,
|
|
978
|
+
` ),
|
|
979
|
+
optional($.order_by),
|
|
980
|
+
optional($.limit),
|
|
981
|
+
),`
|
|
982
|
+
);
|
|
983
|
+
patchRule('op_other', " '<->',", " '<->',\n '<=>',");
|
|
984
|
+
patchRule('_expression', '$.interval,', '$.interval,\n $.at_time_zone,');
|
|
985
|
+
const support = ' $.function_support,\n';
|
|
986
|
+
if (grammar.split(support).length !== 3) throw new Error('SQL function options changed');
|
|
987
|
+
grammar = grammar.replaceAll(support, support + ' $.function_configuration,\n');
|
|
988
|
+
patchRule(
|
|
989
|
+
'grant_statement',
|
|
990
|
+
`comma_list(choice($.keyword_select, $.keyword_insert, $.keyword_update, $.keyword_delete, make_keyword("usage")), true),
|
|
991
|
+
$.keyword_on, optional($.keyword_sequence), comma_list($.object_reference, true),`,
|
|
992
|
+
`$._privilege_list,
|
|
993
|
+
$.keyword_on, $._privilege_target,`
|
|
994
|
+
);
|
|
995
|
+
patch(
|
|
996
|
+
' _cte: $ => seq(',
|
|
997
|
+
` _privilege_list: $ => comma_list(choice(
|
|
998
|
+
$.keyword_select, $.keyword_insert, $.keyword_update, $.keyword_delete,
|
|
999
|
+
make_keyword("usage"), make_keyword("execute"), make_keyword("truncate"),
|
|
1000
|
+
seq($.keyword_all, optional(make_keyword("privileges")))
|
|
1001
|
+
), true),
|
|
1002
|
+
routine_signature: $ => seq($.object_reference, optional($.function_arguments)),
|
|
1003
|
+
_privilege_target: $ => choice(
|
|
1004
|
+
seq($.keyword_function, comma_list($.routine_signature, true)),
|
|
1005
|
+
seq($.keyword_schema, comma_list($.identifier, true)),
|
|
1006
|
+
seq($.keyword_all, choice(make_keyword("tables"), make_keyword("sequences"), make_keyword("functions")),
|
|
1007
|
+
$.keyword_in, $.keyword_schema, comma_list($.identifier, true)),
|
|
1008
|
+
seq(optional(choice($.keyword_table, $.keyword_sequence)), comma_list($.object_reference, true))
|
|
1009
|
+
),
|
|
1010
|
+
revoke_statement: $ => seq(make_keyword("revoke"), $._privilege_list, $.keyword_on,
|
|
1011
|
+
$._privilege_target, $.keyword_from, comma_list($.identifier, true)),
|
|
1012
|
+
alter_default_privileges: $ => seq(
|
|
1013
|
+
$.keyword_alter, $.keyword_default, make_keyword("privileges"),
|
|
1014
|
+
optional(seq($.keyword_for, $.keyword_role, comma_list($.identifier, true))),
|
|
1015
|
+
optional(seq($.keyword_in, $.keyword_schema, comma_list($.identifier, true))),
|
|
1016
|
+
choice(
|
|
1017
|
+
seq(make_keyword("grant"), $._privilege_list, $.keyword_on,
|
|
1018
|
+
choice(make_keyword("tables"), make_keyword("sequences"), make_keyword("functions")),
|
|
1019
|
+
$.keyword_to, comma_list($.identifier, true)),
|
|
1020
|
+
seq(make_keyword("revoke"), $._privilege_list, $.keyword_on,
|
|
1021
|
+
choice(make_keyword("tables"), make_keyword("sequences"), make_keyword("functions")),
|
|
1022
|
+
$.keyword_from, comma_list($.identifier, true))
|
|
1023
|
+
)
|
|
1024
|
+
),
|
|
1025
|
+
drop_policy: $ => seq($.keyword_drop, make_keyword("policy"), optional($._if_exists),
|
|
1026
|
+
$.identifier, $.keyword_on, alias($.policy_relation, $.relation)),
|
|
1027
|
+
alter_policy: $ => seq($.keyword_alter, make_keyword("policy"), $.identifier,
|
|
1028
|
+
$.keyword_on, alias($.policy_relation, $.relation), $.keyword_rename, $.keyword_to, $.identifier),
|
|
1029
|
+
function_configuration: $ => seq($.keyword_set, $.object_reference,
|
|
1030
|
+
choice(seq($.keyword_from, make_keyword("current")),
|
|
1031
|
+
seq(choice('=', $.keyword_to), comma_list(choice($.literal, $.identifier), true)))),
|
|
1032
|
+
_procedure_option: $ => choice($.function_security, $.function_configuration),
|
|
1033
|
+
create_procedure: $ => seq(
|
|
1034
|
+
$.keyword_create, optional($._or_replace), $.keyword_procedure,
|
|
1035
|
+
$.object_reference, $.function_arguments, repeat($._procedure_option),
|
|
1036
|
+
choice(
|
|
1037
|
+
seq($.function_language, repeat($._procedure_option), alias($.opaque_function_body, $.function_body)),
|
|
1038
|
+
seq(alias($.opaque_function_body, $.function_body), repeat($._procedure_option), $.function_language)
|
|
1039
|
+
), repeat($._procedure_option)
|
|
1040
|
+
),
|
|
1041
|
+
drop_procedure: $ => seq($.keyword_drop, $.keyword_procedure, optional($._if_exists),
|
|
1042
|
+
$.routine_signature, optional($._drop_behavior)),
|
|
1043
|
+
call_statement: $ => seq(make_keyword("call"), $.invocation),
|
|
1044
|
+
analyze_statement: $ => seq($.keyword_analyze, $.object_reference, optional(paren_list($.identifier, true))),
|
|
1045
|
+
lock_statement: $ => seq(make_keyword("lock"), $.keyword_table, comma_list($.object_reference, true),
|
|
1046
|
+
$.keyword_in, choice(seq(make_keyword("share"), $.keyword_row, make_keyword("exclusive")),
|
|
1047
|
+
seq(make_keyword("access"), make_keyword("exclusive"))), make_keyword("mode")),
|
|
1048
|
+
prepare_statement: $ => seq(make_keyword("prepare"), $.identifier,
|
|
1049
|
+
optional(paren_list($._type, true)), $.keyword_as, choice($._dml_read, $._dml_write)),
|
|
1050
|
+
execute_statement: $ => seq(make_keyword("execute"), $.identifier, optional(paren_list($._expression))),
|
|
1051
|
+
at_time_zone: $ => prec.left('binary_times', seq($._expression,
|
|
1052
|
+
make_keyword("at"), make_keyword("time"), make_keyword("zone"), $._expression)),
|
|
1053
|
+
|
|
1054
|
+
_cte: $ => seq(`
|
|
1055
|
+
);
|
|
626
1056
|
const functionStart = grammar.indexOf(' create_function: $ => seq(');
|
|
627
1057
|
const functionEnd = grammar.indexOf(' _function_return:', functionStart);
|
|
628
1058
|
if (functionStart < 0 || functionEnd < 0) throw new Error('SQL function patch no longer applies');
|
|
@@ -936,9 +1366,95 @@ function rebuildBash(dir: string, work: string): void {
|
|
|
936
1366
|
);
|
|
937
1367
|
}
|
|
938
1368
|
|
|
1369
|
+
/** Reuse the existing offline WASM toolchain; never install native grammar bindings. */
|
|
1370
|
+
function buildPrerequisite(dir: string, work: string, spec: GrammarSpec): void {
|
|
1371
|
+
const config = join(dir, 'tree-sitter.json');
|
|
1372
|
+
const buildRepositories: Record<string, string> = {
|
|
1373
|
+
clojure: 'https://github.com/oakmac/tree-sitter-clojure',
|
|
1374
|
+
zig: 'https://github.com/GrayJack/tree-sitter-zig',
|
|
1375
|
+
graphql: 'https://github.com/bkegley/tree-sitter-graphql',
|
|
1376
|
+
};
|
|
1377
|
+
if (!existsSync(config) && buildRepositories[spec.id]) {
|
|
1378
|
+
// Old packages omit the build metadata required by the current WASM builder.
|
|
1379
|
+
writeFileSync(
|
|
1380
|
+
config,
|
|
1381
|
+
JSON.stringify({
|
|
1382
|
+
grammars: [
|
|
1383
|
+
{
|
|
1384
|
+
name: spec.id === 'protobuf' ? 'proto' : spec.id,
|
|
1385
|
+
scope: `source.${spec.id}`,
|
|
1386
|
+
path: '.',
|
|
1387
|
+
'file-types': [],
|
|
1388
|
+
},
|
|
1389
|
+
],
|
|
1390
|
+
metadata: {
|
|
1391
|
+
version: (
|
|
1392
|
+
JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8')) as { version: string }
|
|
1393
|
+
).version,
|
|
1394
|
+
license: spec.id === 'zig' ? 'BSD-3-Clause' : 'MIT',
|
|
1395
|
+
description: 'Pinned parser WASM build',
|
|
1396
|
+
authors: [],
|
|
1397
|
+
links: { repository: buildRepositories[spec.id] },
|
|
1398
|
+
},
|
|
1399
|
+
bindings: {},
|
|
1400
|
+
})
|
|
1401
|
+
);
|
|
1402
|
+
}
|
|
1403
|
+
if (spec.id === 'graphql') {
|
|
1404
|
+
// The pinned quoted-string rule rejects every escape, including valid GraphQL \n.
|
|
1405
|
+
// Keep the upstream block-string rule and all source offsets unchanged.
|
|
1406
|
+
const path = join(dir, 'grammar.js');
|
|
1407
|
+
const grammar = readFileSync(path, 'utf8');
|
|
1408
|
+
const before = String.raw`seq('"', /[^"\\\n]*/, '"')`;
|
|
1409
|
+
const after = String.raw`seq('"', /([^"\\\r\n]|\\(["\\/bfnrt]|u[0-9a-fA-F]{4}))*/, '"')`;
|
|
1410
|
+
if (!grammar.includes(before)) throw new Error('GraphQL string escape patch no longer applies');
|
|
1411
|
+
writeFileSync(path, grammar.replace(before, after));
|
|
1412
|
+
}
|
|
1413
|
+
if (spec.id === 'zig') {
|
|
1414
|
+
const path = join(dir, 'grammar.js');
|
|
1415
|
+
const grammar = readFileSync(path, 'utf8');
|
|
1416
|
+
const before = '/u{[0-9a-fA-F]+}/';
|
|
1417
|
+
if (!grammar.includes(before))
|
|
1418
|
+
throw new Error('Zig Unicode escape compatibility patch no longer applies');
|
|
1419
|
+
writeFileSync(path, grammar.replace(before, String.raw`/u\{[0-9a-fA-F]+\}/`));
|
|
1420
|
+
}
|
|
1421
|
+
const tools = join(work, 'prerequisite-build');
|
|
1422
|
+
const cli = join(tools, 'node_modules', '.bin', 'tree-sitter');
|
|
1423
|
+
if (!existsSync(cli)) {
|
|
1424
|
+
execFileSync('npm', [
|
|
1425
|
+
'install',
|
|
1426
|
+
'--prefix',
|
|
1427
|
+
tools,
|
|
1428
|
+
'--no-audit',
|
|
1429
|
+
'--no-fund',
|
|
1430
|
+
'--no-package-lock',
|
|
1431
|
+
'tree-sitter-cli@0.24.4',
|
|
1432
|
+
]);
|
|
1433
|
+
}
|
|
1434
|
+
const deadline = Date.now() + 300_000;
|
|
1435
|
+
if (spec.build === 'regenerate') {
|
|
1436
|
+
execFileSync(cli, ['generate'], { cwd: dir, timeout: 300_000 });
|
|
1437
|
+
}
|
|
1438
|
+
execFileSync(
|
|
1439
|
+
cli,
|
|
1440
|
+
[
|
|
1441
|
+
'build',
|
|
1442
|
+
'--wasm',
|
|
1443
|
+
'--docker',
|
|
1444
|
+
'--output',
|
|
1445
|
+
join(dir, spec.wasmFile ?? `tree-sitter-${spec.id}.wasm`),
|
|
1446
|
+
],
|
|
1447
|
+
{
|
|
1448
|
+
cwd: dir,
|
|
1449
|
+
timeout: Math.max(1, deadline - Date.now()),
|
|
1450
|
+
}
|
|
1451
|
+
);
|
|
1452
|
+
}
|
|
1453
|
+
|
|
939
1454
|
function vendor(): Problem[] {
|
|
940
1455
|
const only = process.argv.find((arg) => arg.startsWith('--only='))?.slice(7);
|
|
941
|
-
|
|
1456
|
+
const selected = only?.split(',');
|
|
1457
|
+
if (selected?.some((id) => !GRAMMARS.some((spec) => spec.id === id)))
|
|
942
1458
|
throw new Error(`Unknown grammar: ${only}`);
|
|
943
1459
|
mkdirSync(WASM_DIR, { recursive: true });
|
|
944
1460
|
const work = mkdtempSync(join(tmpdir(), 'ts-grammars-'));
|
|
@@ -949,7 +1465,7 @@ function vendor(): Problem[] {
|
|
|
949
1465
|
|
|
950
1466
|
try {
|
|
951
1467
|
for (const spec of GRAMMARS) {
|
|
952
|
-
if (
|
|
1468
|
+
if (selected && !selected.includes(spec.id)) continue;
|
|
953
1469
|
let dir = extracted.get(spec.pkg);
|
|
954
1470
|
if (!dir) {
|
|
955
1471
|
try {
|
|
@@ -982,6 +1498,7 @@ function vendor(): Problem[] {
|
|
|
982
1498
|
if (spec.id === 'cpp') rebuildCpp(dir, work);
|
|
983
1499
|
if (spec.id === 'bash') rebuildBash(dir, work);
|
|
984
1500
|
if (spec.id === 'nix' || spec.id === 'cmake') rebuildNixOrCmake(dir, work, spec.id);
|
|
1501
|
+
if (spec.build) buildPrerequisite(dir, work, spec);
|
|
985
1502
|
}
|
|
986
1503
|
extracted.set(spec.pkg, dir);
|
|
987
1504
|
} catch (err) {
|
|
@@ -999,7 +1516,18 @@ function vendor(): Problem[] {
|
|
|
999
1516
|
if (!existsSync(wasmSrc)) {
|
|
1000
1517
|
problems.push({ id: spec.id, detail: `${spec.pkg} ships no ${wasmName}` });
|
|
1001
1518
|
} else {
|
|
1002
|
-
|
|
1519
|
+
const compressed = gzipSync(readFileSync(wasmSrc), { level: 9 });
|
|
1520
|
+
// Timestamp is zero in Node gzip; normalize the OS byte across build hosts too.
|
|
1521
|
+
compressed[9] = 255;
|
|
1522
|
+
writeFileSync(join(WASM_DIR, `${spec.id}.wasm.gz`), compressed, { mode: 0o644 });
|
|
1523
|
+
rmSync(join(WASM_DIR, `${spec.id}.wasm`), { force: true });
|
|
1524
|
+
if (spec.licenseFile)
|
|
1525
|
+
writeFileSync(
|
|
1526
|
+
join(WASM_DIR, `${spec.id}.LICENSE`),
|
|
1527
|
+
readFileSync(join(dir, spec.licenseFile), 'utf8')
|
|
1528
|
+
.replace(/\r\n/g, '\n')
|
|
1529
|
+
.replace(/[\u201c\u201d]/g, '"')
|
|
1530
|
+
);
|
|
1003
1531
|
if (spec.id === 'lua') copyFileSync(join(dir, 'LICENSE.md'), join(WASM_DIR, 'lua.LICENSE'));
|
|
1004
1532
|
if (spec.id === 'terraform')
|
|
1005
1533
|
copyFileSync(join(dir, 'LICENSE'), join(WASM_DIR, 'terraform.LICENSE'));
|
|
@@ -1013,7 +1541,7 @@ function vendor(): Problem[] {
|
|
|
1013
1541
|
spec.id === 'nix' ||
|
|
1014
1542
|
spec.id === 'cmake'
|
|
1015
1543
|
)
|
|
1016
|
-
chmodSync(join(WASM_DIR, `${spec.id}.wasm`), 0o644);
|
|
1544
|
+
chmodSync(join(WASM_DIR, `${spec.id}.wasm.gz`), 0o644);
|
|
1017
1545
|
}
|
|
1018
1546
|
|
|
1019
1547
|
// A targeted JS scanner rebuild must retain our module-scope binding query additions.
|
|
@@ -1056,11 +1584,15 @@ if (problems.length > 0) {
|
|
|
1056
1584
|
process.exit(1);
|
|
1057
1585
|
}
|
|
1058
1586
|
|
|
1059
|
-
const sizes = GRAMMARS.map((g) => statSync(join(WASM_DIR, `${g.id}.wasm`)).size);
|
|
1587
|
+
const sizes = GRAMMARS.map((g) => statSync(join(WASM_DIR, `${g.id}.wasm.gz`)).size);
|
|
1060
1588
|
const totalBytes = sizes.reduce((a, b) => a + b, 0);
|
|
1589
|
+
const inflatedBytes = GRAMMARS.reduce(
|
|
1590
|
+
(total, g) => total + gunzipSync(readFileSync(join(WASM_DIR, `${g.id}.wasm.gz`))).length,
|
|
1591
|
+
0
|
|
1592
|
+
);
|
|
1061
1593
|
const totalMB = +(totalBytes / 1048576).toFixed(1);
|
|
1062
1594
|
console.log(
|
|
1063
|
-
`VENDOR_GRAMMARS_OK ${JSON.stringify({ grammars: GRAMMARS.length, totalWasmMB: totalMB })}`
|
|
1595
|
+
`VENDOR_GRAMMARS_OK ${JSON.stringify({ grammars: GRAMMARS.length, shippedBytes: totalBytes, inflatedBytes, totalWasmMB: totalMB })}`
|
|
1064
1596
|
);
|
|
1065
1597
|
// Owner-approved Objective-C++ cost: repaired bundle 43.58 MiB (43.67 with Terraform 667475e93), bounded at 45 MiB.
|
|
1066
1598
|
if (totalBytes > 45 * 1048576) {
|