tree-sitter / tree-sitter-haskell

Haskell grammar for tree-sitter.
MIT License
152 stars 36 forks source link

WASM build fails with error #53

Closed wenkokke closed 2 years ago

wenkokke commented 2 years ago

Using the wasm generated with npx tree-sitter build-wasm fails with the following error:

Aborted(Assertion failed: undefined symbol `_ZNSt3__24cerrE`. 
    perhaps a side module was not linked in? 
    if this global was expected to arrive from a system library, 
    try to build the MAIN_MODULE with EMCC_FORCE_STDLIBS=1 in the environment)
wenkokke commented 2 years ago

Compiling web-tree-sitter using ASSERTIONS=1, via script/build-wasm --debug, refines the error message to:

Aborted(Assertion failed: undefined symbol `_ZTVN10__cxxabiv117__class_type_infoE`. 
    perhaps a side module was not linked in?
    if this global was expected to arrive from a system library, 
    try to build the MAIN_MODULE with EMCC_FORCE_STDLIBS=1 in the environment)

Compiling with EMCC_FORCE_STDLIBS=1 does not make a difference.

wenkokke commented 2 years ago

The issue is that web-tree-sitter performs dead code elimination, and eliminates all but a select few functions listed in exports.json. The following patch to tree-sitter ensures that the functions used by tree-sitter-haskell are kept:

diff --git a/lib/binding_web/exports.json b/lib/binding_web/exports.json
index e0b3f718..36342e52 100644
--- a/lib/binding_web/exports.json
+++ b/lib/binding_web/exports.json
@@ -3,6 +3,15 @@
   "_free",
   "_malloc",

+  "__ZNSt3__24cerrE",
+  "__ZNSt3__25ctypeIcE2idE",
+  "__ZTVN10__cxxabiv117__class_type_infoE",
+  "__ZTVN10__cxxabiv120__si_class_type_infoE",
+  "__ZTVN10__cxxabiv120__function_type_infoE",
+  "__ZTVN10__cxxabiv119__pointer_type_infoE",
+  "__ZTVN10__cxxabiv121__vmi_class_type_infoE",
+  "___cxa_pure_virtual",
+
   "__ZNKSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE4copyEPcmm",
   "__ZNKSt3__220__vector_base_commonILb1EE20__throw_length_errorEv",
   "__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEPKcm",

However, I suppose such a patch is unlikely to be accepted. Is the use of these functions really worth the hassle?

wenkokke commented 2 years ago

With the above patch applied to tree-sitter running a simple parser test results in the following error:

TypeError: Cannot read properties of undefined (reading 'apply')
    at e.<computed> (tree-sitter-haskell/node_modules/web-tree-sitter/tree-sitter.js:1:10543)
    at wasm://wasm/00ea81ae:wasm-function[2590]:0xc09ac
    at e.<computed> (tree-sitter-haskell/node_modules/web-tree-sitter/tree-sitter.js:1:10543)
    at wasm://wasm/00ea81ae:wasm-function[2962]:0xc55b5
    at e.<computed> (tree-sitter-haskell/node_modules/web-tree-sitter/tree-sitter.js:1:10543)
    at wasm://wasm/00ea81ae:wasm-function[2961]:0xc55a8
    at e.<computed> (tree-sitter-haskell/node_modules/web-tree-sitter/tree-sitter.js:1:10543)
    at wasm://wasm/00ea81ae:wasm-function[2939]:0xc5468
    at e.<computed> (tree-sitter-haskell/node_modules/web-tree-sitter/tree-sitter.js:1:10543)
    at wasm://wasm/00ea81ae:wasm-function[2583]:0xc089a
wenkokke commented 2 years ago

To help reproducing these errors, here is a simple script which uses the generated wasm, to be called as script/parse-example.js:

#!/usr/bin/env node

const fs = require('fs')
const Parser = require('web-tree-sitter');

if (process.argv.length < 3) {
  console.log('Usage: script/parse-example.js <haskell-file>')
  process.exit(1)
}

const fileName = process.argv[2]
const sourceCode = fs.readFileSync(fileName, 'utf8')

Parser.init().then(() => {
  Parser.Language.load('tree-sitter-haskell.wasm').then((Haskell) => {
    const parser = new Parser;
    parser.setLanguage(Haskell);
    const tree = parser.parse(sourceCode);
    console.log(tree.rootNode.toString());
  });
});
wenkokke commented 2 years ago

The following patch to web-tree-sitter makes tree-sitter-haskell work:

diff --git a/lib/binding_web/exports.json b/lib/binding_web/exports.json
index e0b3f718..3a43ae33 100644
--- a/lib/binding_web/exports.json
+++ b/lib/binding_web/exports.json
@@ -3,6 +3,17 @@
   "_free",
   "_malloc",

+  "__ZNSt3__24cerrE",
+  "__ZNSt3__25ctypeIcE2idE",
+  "__ZTVN10__cxxabiv117__class_type_infoE",
+  "__ZTVN10__cxxabiv120__si_class_type_infoE",
+  "__ZTVN10__cxxabiv120__function_type_infoE",
+  "__ZTVN10__cxxabiv119__pointer_type_infoE",
+  "__ZTVN10__cxxabiv121__vmi_class_type_infoE",
+  "__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE25__init_copy_ctor_externalEPKcm",
+  "__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE25__init_copy_ctor_externalEPKcm",
+  "___cxa_pure_virtual",
+
   "__ZNKSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE4copyEPcmm",
   "__ZNKSt3__220__vector_base_commonILb1EE20__throw_length_errorEv",
   "__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEPKcm",
wenkokke commented 2 years ago

Created two issues which may help debug such problems in the future (https://github.com/tree-sitter/tree-sitter/issues/1565 and https://github.com/tree-sitter/tree-sitter/issues/1566).