@mnemonik/shared 7.144.2 → 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 +551 -35
- 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'));
|
|
@@ -513,6 +651,18 @@ function vendorObjcpp(work: string, repository: string): string {
|
|
|
513
651
|
]);
|
|
514
652
|
git(['checkout', '--quiet', '--detach', 'FETCH_HEAD']);
|
|
515
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);
|
|
516
666
|
const tools = join(work, 'objcpp-build');
|
|
517
667
|
execFileSync('npm', [
|
|
518
668
|
'install',
|
|
@@ -522,10 +672,17 @@ function vendorObjcpp(work: string, repository: string): string {
|
|
|
522
672
|
'--no-fund',
|
|
523
673
|
'--no-package-lock',
|
|
524
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',
|
|
525
678
|
]);
|
|
526
|
-
|
|
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
|
+
});
|
|
527
684
|
execFileSync(
|
|
528
|
-
|
|
685
|
+
cli,
|
|
529
686
|
['build', '--wasm', '--docker', '--output', join(dir, 'tree-sitter-objcpp.wasm')],
|
|
530
687
|
{ cwd: dir }
|
|
531
688
|
);
|
|
@@ -611,12 +768,35 @@ function rebuildSql(dir: string, work: string): void {
|
|
|
611
768
|
$.keyword_create, make_keyword("policy"), field('name', $.identifier),
|
|
612
769
|
$.keyword_on, alias($.policy_relation, $.relation),
|
|
613
770
|
optional(seq($.keyword_for, choice($.keyword_select, $.keyword_insert, $.keyword_update, $.keyword_delete))),
|
|
614
|
-
optional(seq($.keyword_to, $.identifier)),
|
|
771
|
+
optional(seq($.keyword_to, comma_list($.identifier, true))),
|
|
615
772
|
optional(seq($.keyword_using, wrapped_in_parenthesis($._expression))),
|
|
616
773
|
optional(seq($.keyword_with, $.keyword_check, wrapped_in_parenthesis($._expression))),
|
|
617
774
|
),
|
|
618
775
|
create_table: $ => prec.left(`
|
|
619
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
|
+
);
|
|
620
800
|
// Dollar-quoted procedural code is one literal, never a parsed SQL statement list.
|
|
621
801
|
patch(' $.reset_statement,', ' $.reset_statement,\n $.do_statement,');
|
|
622
802
|
patch(
|
|
@@ -639,6 +819,240 @@ function rebuildSql(dir: string, work: string): void {
|
|
|
639
819
|
' conflicts: $ => [',
|
|
640
820
|
' conflicts: $ => [\n [$._expression, $._inner_default_expression],\n [$.create_function],'
|
|
641
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
|
+
);
|
|
642
1056
|
const functionStart = grammar.indexOf(' create_function: $ => seq(');
|
|
643
1057
|
const functionEnd = grammar.indexOf(' _function_return:', functionStart);
|
|
644
1058
|
if (functionStart < 0 || functionEnd < 0) throw new Error('SQL function patch no longer applies');
|
|
@@ -952,9 +1366,95 @@ function rebuildBash(dir: string, work: string): void {
|
|
|
952
1366
|
);
|
|
953
1367
|
}
|
|
954
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
|
+
|
|
955
1454
|
function vendor(): Problem[] {
|
|
956
1455
|
const only = process.argv.find((arg) => arg.startsWith('--only='))?.slice(7);
|
|
957
|
-
|
|
1456
|
+
const selected = only?.split(',');
|
|
1457
|
+
if (selected?.some((id) => !GRAMMARS.some((spec) => spec.id === id)))
|
|
958
1458
|
throw new Error(`Unknown grammar: ${only}`);
|
|
959
1459
|
mkdirSync(WASM_DIR, { recursive: true });
|
|
960
1460
|
const work = mkdtempSync(join(tmpdir(), 'ts-grammars-'));
|
|
@@ -965,7 +1465,7 @@ function vendor(): Problem[] {
|
|
|
965
1465
|
|
|
966
1466
|
try {
|
|
967
1467
|
for (const spec of GRAMMARS) {
|
|
968
|
-
if (
|
|
1468
|
+
if (selected && !selected.includes(spec.id)) continue;
|
|
969
1469
|
let dir = extracted.get(spec.pkg);
|
|
970
1470
|
if (!dir) {
|
|
971
1471
|
try {
|
|
@@ -998,6 +1498,7 @@ function vendor(): Problem[] {
|
|
|
998
1498
|
if (spec.id === 'cpp') rebuildCpp(dir, work);
|
|
999
1499
|
if (spec.id === 'bash') rebuildBash(dir, work);
|
|
1000
1500
|
if (spec.id === 'nix' || spec.id === 'cmake') rebuildNixOrCmake(dir, work, spec.id);
|
|
1501
|
+
if (spec.build) buildPrerequisite(dir, work, spec);
|
|
1001
1502
|
}
|
|
1002
1503
|
extracted.set(spec.pkg, dir);
|
|
1003
1504
|
} catch (err) {
|
|
@@ -1015,7 +1516,18 @@ function vendor(): Problem[] {
|
|
|
1015
1516
|
if (!existsSync(wasmSrc)) {
|
|
1016
1517
|
problems.push({ id: spec.id, detail: `${spec.pkg} ships no ${wasmName}` });
|
|
1017
1518
|
} else {
|
|
1018
|
-
|
|
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
|
+
);
|
|
1019
1531
|
if (spec.id === 'lua') copyFileSync(join(dir, 'LICENSE.md'), join(WASM_DIR, 'lua.LICENSE'));
|
|
1020
1532
|
if (spec.id === 'terraform')
|
|
1021
1533
|
copyFileSync(join(dir, 'LICENSE'), join(WASM_DIR, 'terraform.LICENSE'));
|
|
@@ -1029,7 +1541,7 @@ function vendor(): Problem[] {
|
|
|
1029
1541
|
spec.id === 'nix' ||
|
|
1030
1542
|
spec.id === 'cmake'
|
|
1031
1543
|
)
|
|
1032
|
-
chmodSync(join(WASM_DIR, `${spec.id}.wasm`), 0o644);
|
|
1544
|
+
chmodSync(join(WASM_DIR, `${spec.id}.wasm.gz`), 0o644);
|
|
1033
1545
|
}
|
|
1034
1546
|
|
|
1035
1547
|
// A targeted JS scanner rebuild must retain our module-scope binding query additions.
|
|
@@ -1072,11 +1584,15 @@ if (problems.length > 0) {
|
|
|
1072
1584
|
process.exit(1);
|
|
1073
1585
|
}
|
|
1074
1586
|
|
|
1075
|
-
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);
|
|
1076
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
|
+
);
|
|
1077
1593
|
const totalMB = +(totalBytes / 1048576).toFixed(1);
|
|
1078
1594
|
console.log(
|
|
1079
|
-
`VENDOR_GRAMMARS_OK ${JSON.stringify({ grammars: GRAMMARS.length, totalWasmMB: totalMB })}`
|
|
1595
|
+
`VENDOR_GRAMMARS_OK ${JSON.stringify({ grammars: GRAMMARS.length, shippedBytes: totalBytes, inflatedBytes, totalWasmMB: totalMB })}`
|
|
1080
1596
|
);
|
|
1081
1597
|
// Owner-approved Objective-C++ cost: repaired bundle 43.58 MiB (43.67 with Terraform 667475e93), bounded at 45 MiB.
|
|
1082
1598
|
if (totalBytes > 45 * 1048576) {
|