diff --git a/lib/binding_web/package.json b/lib/binding_web/package.json index 68202234..8425a274 100644 --- a/lib/binding_web/package.json +++ b/lib/binding_web/package.json @@ -44,6 +44,7 @@ "esbuild": "^0.24.2", "eslint": "^9.18.0", "source-map": "^0.7.4", + "tsx": "^4.19.2", "typescript": "^5.7.3", "typescript-eslint": "^8.20.0", "vitest": "^3.0.2" @@ -51,13 +52,16 @@ "scripts": { "build:ts": "esbuild src/index.ts --bundle --platform=neutral --format=cjs --global-name=TreeSitterImpl --outfile=dist/tree-sitter.js --external:fs/* --external:fs/promises --sourcemap --sources-content=true --keep-names", "build:wasm": "cd ../../ && cargo xtask build-wasm", - "build:sourcemap": "node script/build-sourcemap.js", + "build:wasm:debug": "cd ../../ && cargo xtask build-wasm --debug", + "build:sourcemap": "tsx script/build-sourcemap.ts", "build": "npm run build:ts && npm run build:wasm && npm run build:sourcemap", - "build:debug": "npm run build:ts && npm run build:wasm:debug && mkdir -p debug && mv tree-sitter.* debug/", + "build:debug": "npm run build:ts && npm run build:wasm:debug && cp debug/* . && npm run build:sourcemap", + "lint": "eslint src/*.ts script/*.ts", + "lint:fix": "eslint src/*.ts script/*.ts --fix", "test": "vitest run", "test:watch": "vitest", "prepack": "cp ../../LICENSE .", - "prepublishOnly": "node script/check-artifacts-fresh.js", - "postinstall": "node scripts/postinstall.js" + "prepublishOnly": "tsx script/check-artifacts-fresh.ts", + "postinstall": "node script/postinstall.js" } } diff --git a/lib/binding_web/script/build-sourcemap.js b/lib/binding_web/script/build-sourcemap.ts similarity index 75% rename from lib/binding_web/script/build-sourcemap.js rename to lib/binding_web/script/build-sourcemap.ts index 08cc1345..e35e0d31 100644 --- a/lib/binding_web/script/build-sourcemap.js +++ b/lib/binding_web/script/build-sourcemap.ts @@ -1,20 +1,22 @@ import { readFileSync, writeFileSync } from 'fs'; -import { SourceMapGenerator, SourceMapConsumer } from 'source-map'; +import { SourceMapGenerator, SourceMapConsumer, RawSourceMap } from 'source-map'; async function fixSourceMap() { - const distMap = JSON.parse(readFileSync('dist/tree-sitter.js.map', 'utf8')); + const distMap = JSON.parse(readFileSync('dist/tree-sitter.js.map', 'utf8')) as RawSourceMap; const distJs = readFileSync('dist/tree-sitter.js', 'utf8').split('\n'); const finalJs = readFileSync('tree-sitter.js', 'utf8').split('\n'); - const lineMap = new Map(); + const lineMap = new Map(); + let currentFinalLine = 0; for (let distLine = 0; distLine < distJs.length; distLine++) { const line = distJs[distLine].trim(); if (!line) continue; - for (let finalLine = 0; finalLine < finalJs.length; finalLine++) { + for (let finalLine = currentFinalLine; finalLine < finalJs.length; finalLine++) { if (finalJs[finalLine].trim() === line) { lineMap.set(distLine + 1, finalLine + 1); + currentFinalLine = finalLine; break; } } @@ -23,7 +25,7 @@ async function fixSourceMap() { const consumer = await new SourceMapConsumer(distMap); const generator = new SourceMapGenerator({ file: 'tree-sitter.js', - sourceRoot: '' + sourceRoot: '', }); consumer.eachMapping(mapping => { @@ -32,15 +34,15 @@ async function fixSourceMap() { generator.addMapping({ generated: { line: finalLine, - column: mapping.generatedColumn + column: mapping.generatedColumn, }, original: { line: mapping.originalLine, - column: mapping.originalColumn + column: mapping.originalColumn, }, // Fix the source path to be relative to binding_web source: `src/${mapping.source.split('/').pop()}`, - name: mapping.name + name: mapping.name, }); } }); @@ -50,7 +52,7 @@ async function fixSourceMap() { if (content) { generator.setSourceContent( `src/${source.split('/').pop()}`, - content + content, ); } } diff --git a/lib/binding_web/script/check-artifacts-fresh.js b/lib/binding_web/script/check-artifacts-fresh.js deleted file mode 100755 index 53fb3661..00000000 --- a/lib/binding_web/script/check-artifacts-fresh.js +++ /dev/null @@ -1,34 +0,0 @@ -const fs = require('fs'); -const path = require('path'); - -const inputFiles = [ - 'lib/binding.c', - 'binding.js', - 'wasm/exports.txt', - 'wasm/imports.js', - 'prefix.js', - ...list('../include/tree_sitter'), - ...list('../src'), -]; - -const outputFiles = ['tree-sitter.js', 'tree-sitter.wasm']; - -const outputMtime = Math.min(...outputFiles.map(mtime)); - -for (const inputFile of inputFiles) { - if (mtime(inputFile) > outputMtime) { - console.log(`File '${inputFile}' has changed. Re-run 'script/build-wasm'.`); - process.exit(1); - } -} - -function list(dir) { - return fs - .readdirSync(path.join(__dirname, dir), 'utf8') - .filter((p) => !p.startsWith('.')) - .map((p) => path.join(dir, p)); -} - -function mtime(p) { - return fs.statSync(path.join(__dirname, p)).mtime; -} diff --git a/lib/binding_web/script/check-artifacts-fresh.ts b/lib/binding_web/script/check-artifacts-fresh.ts new file mode 100755 index 00000000..7cf91788 --- /dev/null +++ b/lib/binding_web/script/check-artifacts-fresh.ts @@ -0,0 +1,46 @@ +import fs from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'node:url'; + +const scriptDir = path.dirname(fileURLToPath(import.meta.url)); + +const inputFiles = [ + '../lib/tree-sitter.c', + '../src/constants.ts', + '../src/index.ts', + '../src/language.ts', + '../src/lookahead_iterator.ts', + '../src/marshal.ts', + '../src/node.ts', + '../src/parser.ts', + '../src/query.ts', + '../src/tree.ts', + '../src/tree_cursor.ts', + '../dist/tree-sitter.js', + '../wasm/exports.txt', + '../wasm/imports.js', + '../wasm/prefix.js', + ...listFiles('../../include/tree_sitter'), + ...listFiles('../../src'), +]; + +const outputFiles = ['../tree-sitter.js', '../tree-sitter.wasm']; +const outputMtime = Math.min(...outputFiles.map(getMtime)); + +for (const inputFile of inputFiles) { + if (getMtime(inputFile) > outputMtime) { + console.log(`File '${inputFile}' has changed. Re-run 'npm run build:wasm'.`); + process.exit(1); + } +} + +function listFiles(dir: string): string[] { + return fs + .readdirSync(path.resolve(scriptDir, dir)) + .filter(p => !p.startsWith('.')) + .map(p => path.join(dir, p)); +} + +function getMtime(p: string): number { + return fs.statSync(path.resolve(scriptDir, p)).mtime.getTime(); +} diff --git a/lib/binding_web/script/postinstall.js b/lib/binding_web/script/postinstall.js index 4c2478f7..b673d19b 100644 --- a/lib/binding_web/script/postinstall.js +++ b/lib/binding_web/script/postinstall.js @@ -1,25 +1,24 @@ import fs from 'fs'; import path from 'path'; -const isDebug = process.env.npm_config_web_tree_sitter_debug === 'true'; +const isDebug = process.env.npm_config_debug === 'true'; if (isDebug) { // Copy debug versions to root fs.copyFileSync( path.join(__dirname, '../debug/tree-sitter.js'), - path.join(__dirname, '../tree-sitter.js') + path.join(__dirname, '../tree-sitter.js'), ); fs.copyFileSync( path.join(__dirname, '../debug/tree-sitter.wasm'), - path.join(__dirname, '../tree-sitter.wasm') + path.join(__dirname, '../tree-sitter.wasm'), ); - // Copy sourcemaps too fs.copyFileSync( path.join(__dirname, '../debug/tree-sitter.js.map'), - path.join(__dirname, '../tree-sitter.js.map') + path.join(__dirname, '../tree-sitter.js.map'), ); fs.copyFileSync( path.join(__dirname, '../debug/tree-sitter.wasm.map'), - path.join(__dirname, '../tree-sitter.wasm.map') + path.join(__dirname, '../tree-sitter.wasm.map'), ); }