diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 04eb4786..44994654 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -186,7 +186,14 @@ jobs: - name: Build wasm library # No reason to build on the same Github runner hosts many times if: ${{ !matrix.no-run && !matrix.use-cross }} - run: $BUILD_CMD run -p xtask -- build-wasm + shell: bash + run: | + cd lib/binding_web + npm ci + CJS=true npm run build + CJS=true npm run build:debug + npm run build + npm run build:debug - name: Build target run: $BUILD_CMD build --release --target=${{ matrix.target }} --features=${{ matrix.features }} @@ -236,6 +243,16 @@ jobs: name: tree-sitter.wasm path: | lib/binding_web/tree-sitter.js + lib/binding_web/tree-sitter.js.map + lib/binding_web/tree-sitter.cjs + lib/binding_web/tree-sitter.cjs.map lib/binding_web/tree-sitter.wasm + lib/binding_web/tree-sitter.wasm.map + lib/binding_web/debug/tree-sitter.cjs + lib/binding_web/debug/tree-sitter.cjs.map + lib/binding_web/debug/tree-sitter.js + lib/binding_web/debug/tree-sitter.js.map + lib/binding_web/debug/tree-sitter.wasm + lib/binding_web/debug/tree-sitter.wasm.map if-no-files-found: error retention-days: 7 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4182c45a..a9cb550c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -35,6 +35,23 @@ jobs: run: | mkdir -p target mv artifacts/tree-sitter.wasm/* target/ + + # Rename files + mv target/tree-sitter.js target/web-tree-sitter.js + mv target/tree-sitter.js.map target/web-tree-sitter.js.map + mv target/tree-sitter.cjs target/web-tree-sitter.cjs + mv target/tree-sitter.cjs.map target/web-tree-sitter.cjs.map + mv target/tree-sitter.wasm target/web-tree-sitter.wasm + mv target/tree-sitter.wasm.map target/web-tree-sitter.wasm.map + + mv target/debug/tree-sitter.js target/web-tree-sitter-debug.js + mv target/debug/tree-sitter.js.map target/web-tree-sitter-debug.js.map + mv target/debug/tree-sitter.cjs target/web-tree-sitter-debug.cjs + mv target/debug/tree-sitter.cjs.map target/web-tree-sitter-debug.cjs.map + mv target/debug/tree-sitter.wasm target/web-tree-sitter-debug.wasm + mv target/debug/tree-sitter.wasm.map target/web-tree-sitter-debug.wasm.map + rm -rf target/debug + rm -r artifacts/tree-sitter.wasm for platform in $(cd artifacts; ls | sed 's/^tree-sitter\.//'); do exe=$(ls artifacts/tree-sitter.$platform/tree-sitter*) @@ -47,8 +64,18 @@ jobs: run: |- gh release create ${{ github.ref_name }} \ target/tree-sitter-*.gz \ - target/tree-sitter.wasm \ - target/tree-sitter.js + target/web-tree-sitter.js \ + target/web-tree-sitter.js.map \ + target/web-tree-sitter.cjs \ + target/web-tree-sitter.cjs.map \ + target/web-tree-sitter.wasm \ + target/web-tree-sitter.wasm.map \ + target/web-tree-sitter-debug.js \ + target/web-tree-sitter-debug.js.map \ + target/web-tree-sitter-debug.cjs \ + target/web-tree-sitter-debug.cjs.map \ + target/web-tree-sitter-debug.wasm \ + target/web-tree-sitter-debug.wasm.map env: GH_TOKEN: ${{ github.token }} @@ -91,7 +118,11 @@ jobs: - name: Build wasm if: matrix.directory == 'lib/binding_web' - run: cargo xtask build-wasm + run: | + npm run build + npm run build:debug + CJS=true npm run build + CJS=true npm run build:debug - name: Publish to npmjs.com working-directory: ${{ matrix.directory }} diff --git a/lib/binding_web/.gitignore b/lib/binding_web/.gitignore index 50f811fc..6f3e0840 100644 --- a/lib/binding_web/.gitignore +++ b/lib/binding_web/.gitignore @@ -1,12 +1,9 @@ debug/ dist/ -/lib/tree-sitter.js -/lib/tree-sitter.wasm -/lib/tree-sitter.wasm.map -/tree-sitter.js -/tree-sitter.js.map -/tree-sitter.wasm -/tree-sitter.wasm.map +tree-sitter* +lib/tree-sitter* +!lib/tree-sitter.c +!lib/tree-sitter.d.ts node_modules *.tgz LICENSE diff --git a/lib/binding_web/package-lock.json b/lib/binding_web/package-lock.json index 8cf041d2..283fd0ed 100644 --- a/lib/binding_web/package-lock.json +++ b/lib/binding_web/package-lock.json @@ -14,6 +14,7 @@ "@types/emscripten": "^1.39.13", "@types/node": "^22.10.7", "@vitest/coverage-v8": "^3.0.2", + "dts-buddy": "^0.5.4", "esbuild": "^0.24.2", "eslint": "^9.18.0", "source-map": "^0.7.4", @@ -779,6 +780,17 @@ "node": ">=6.0.0" } }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", @@ -1786,6 +1798,43 @@ "dev": true, "license": "MIT" }, + "node_modules/dts-buddy": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/dts-buddy/-/dts-buddy-0.5.4.tgz", + "integrity": "sha512-a3jJYbMXK98aJvhdV/v+tEKTTEJXXWtMjrl5L8jJL7rnZzGtPA6JNHJZ5//NVRw4JiB5T10Ie5T7h/QsP3aaYw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/source-map": "^0.3.5", + "@jridgewell/sourcemap-codec": "^1.4.15", + "globrex": "^0.1.2", + "kleur": "^4.1.5", + "locate-character": "^3.0.0", + "magic-string": "^0.30.4", + "sade": "^1.8.1", + "tiny-glob": "^0.2.9", + "ts-api-utils": "^1.0.3" + }, + "bin": { + "dts-buddy": "src/cli.js" + }, + "peerDependencies": { + "typescript": ">=5.0.4 <5.8" + } + }, + "node_modules/dts-buddy/node_modules/ts-api-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", + "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -2304,6 +2353,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/globalyzer": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz", + "integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/globrex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", + "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", + "dev": true, + "license": "MIT" + }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", @@ -2529,6 +2592,16 @@ "json-buffer": "3.0.1" } }, + "node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -2543,6 +2616,13 @@ "node": ">= 0.8.0" } }, + "node_modules/locate-character": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz", + "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==", + "dev": true, + "license": "MIT" + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -2678,6 +2758,16 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/mri": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", + "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/mrmime": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", @@ -3033,6 +3123,19 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/sade": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", + "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "mri": "^1.1.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", @@ -3311,6 +3414,17 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/tiny-glob": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz", + "integrity": "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "globalyzer": "0.1.0", + "globrex": "^0.1.2" + } + }, "node_modules/tinybench": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", diff --git a/lib/binding_web/package.json b/lib/binding_web/package.json index f5f82697..325a076a 100644 --- a/lib/binding_web/package.json +++ b/lib/binding_web/package.json @@ -15,8 +15,17 @@ "email": "amaanq12@gmail.com" } ], - "main": "tree-sitter.js", "type": "module", + "exports": { + ".": { + "import": "./tree-sitter.js", + "require": "./tree-sitter.cjs" + }, + "./debug": { + "import": "./debug/tree-sitter.js", + "require": "./debug/tree-sitter.cjs" + } + }, "types": "web-tree-sitter.d.ts", "keywords": [ "incremental", @@ -26,15 +35,21 @@ ], "files": [ "README.md", + "tree-sitter.cjs", + "tree-sitter.cjs.map", "tree-sitter.js", "tree-sitter.js.map", "tree-sitter.wasm", "tree-sitter.wasm.map", - "tree-sitter-web.d.ts", - "debug/tree-sitter.js", - "debug/tree-sitter.js.map", - "debug/tree-sitter.wasm", - "debug/tree-sitter.wasm.map" + "tree-sitter-debug.cjs", + "tree-sitter-debug.cjs.map", + "tree-sitter-debug.js", + "tree-sitter-debug.js.map", + "tree-sitter-debug.wasm", + "tree-sitter-debug.wasm.map", + "web-tree-sitter.d.ts", + "web-tree-sitter.d.ts.map", + "src/**/*.ts" ], "devDependencies": { "@eslint/js": "^9.18.0", @@ -51,18 +66,17 @@ "vitest": "^3.0.2" }, "scripts": { - "build:ts": "esbuild src/index.ts --bundle --format=esm --platform=node --global-name=TreeSitterImpl --outfile=tree-sitter.js --external:fs/* --external:fs/promises --sourcemap --sources-content=true --keep-names && cp lib/*wasm* .", + "build:ts": "node script/build.js", "build:wasm": "cd ../../ && cargo xtask build-wasm", "build:wasm:debug": "cd ../../ && cargo xtask build-wasm --debug", "build": "npm run build:wasm && npm run build:ts", - "build:debug": "npm run build:wasm:debug && npm run build:ts && cp debug/* .", - "lint": "eslint src/*.ts script/*.ts", - "lint:fix": "eslint src/*.ts script/*.ts --fix", + "build:debug": "npm run build:wasm:debug && npm run build:ts -- --debug", "build:dts": "node script/generate-dts.js", + "lint": "eslint src/*.ts script/*.ts test/*.ts", + "lint:fix": "eslint src/*.ts script/*.ts test/*.ts --fix", "test": "vitest run", "test:watch": "vitest", "prepack": "cp ../../LICENSE .", - "prepublishOnly": "tsx script/check-artifacts-fresh.ts", - "postinstall": "node script/postinstall.js" + "prepublishOnly": "tsx script/check-artifacts-fresh.ts" } } diff --git a/lib/binding_web/script/build.js b/lib/binding_web/script/build.js new file mode 100644 index 00000000..bb13c261 --- /dev/null +++ b/lib/binding_web/script/build.js @@ -0,0 +1,23 @@ +import esbuild from 'esbuild'; +import fs from 'fs/promises'; + +const format = process.env.CJS ? 'cjs' : 'esm'; +const debug = process.argv.includes('--debug'); +const outfile = `${debug ? 'debug/' : ''}tree-sitter.${format === 'esm' ? 'js' : 'cjs'}`; + +await esbuild.build({ + entryPoints: ['src/index.ts'], + bundle: true, + platform: 'node', + format, + outfile, + sourcemap: true, + sourcesContent: true, + keepNames: true, + external: ['fs/*', 'fs/promises'], +}); + +// Copy the generated WASM files to the appropriate spot, as esbuild doesn't "bundle" WASM files +const outputWasmName = `${debug ? 'debug/' : ''}tree-sitter.wasm`; +await fs.copyFile(`lib/tree-sitter.wasm`, outputWasmName); +await fs.copyFile(`lib/tree-sitter.wasm.map`, `${outputWasmName}.map`); diff --git a/lib/binding_web/script/postinstall.js b/lib/binding_web/script/postinstall.js deleted file mode 100644 index b673d19b..00000000 --- a/lib/binding_web/script/postinstall.js +++ /dev/null @@ -1,24 +0,0 @@ -import fs from 'fs'; -import path from 'path'; - -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'), - ); - fs.copyFileSync( - path.join(__dirname, '../debug/tree-sitter.wasm'), - path.join(__dirname, '../tree-sitter.wasm'), - ); - fs.copyFileSync( - path.join(__dirname, '../debug/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'), - ); -} diff --git a/xtask/src/build_wasm.rs b/xtask/src/build_wasm.rs index abc8b14e..c0b6c5e8 100644 --- a/xtask/src/build_wasm.rs +++ b/xtask/src/build_wasm.rs @@ -143,7 +143,7 @@ pub fn run_wasm(args: &BuildWasm) -> Result<()> { "-fno-exceptions", "-std=c11", "-s", "WASM=1", - "-s", "EXPORT_ES6", + "-s", "EXPORT_ES6=1", "-s", "MODULARIZE=1", "-s", "INITIAL_MEMORY=33554432", "-s", "ALLOW_MEMORY_GROWTH=1", diff --git a/xtask/src/check_wasm_exports.rs b/xtask/src/check_wasm_exports.rs index 4a09f8a8..50cd3af6 100644 --- a/xtask/src/check_wasm_exports.rs +++ b/xtask/src/check_wasm_exports.rs @@ -71,7 +71,7 @@ fn check_wasm_exports() -> Result<()> { let wasm_objdump = Command::new("wasm-objdump") .args([ "--details", - "lib/binding_web/tree-sitter.wasm", + "lib/binding_web/debug/tree-sitter.wasm", "--section", "Name", ]) diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 5ab23a8e..84825957 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -314,12 +314,10 @@ macro_rules! watch_wasm { } let watch_files = [ - "binding.c", - "binding.js", - "exports.txt", - "imports.js", - "prefix.js", - "suffix.js", + "lib/tree-sitter.c", + "lib/exports.txt", + "lib/imports.js", + "lib/prefix.js", ] .iter() .map(PathBuf::from)