SQLite Forum

WASM sqlite3InitModule() fails if global Array prototype has been extended
Login

WASM sqlite3InitModule() fails if global Array prototype has been extended

(1) By Grant Cox (grantcox) on 2024-05-09 16:45:07 [source]

I just reported this to https://github.com/sqlite/sqlite-wasm/issues/71, but have realized that is probably the wrong place, and this forum is the better location. Apologies for that.

I am migrating an existing Ember application from sql.js to sqlite-wasm. By default, Ember will extend the global Array prototype with some helper functions.

These prototype extensions will be enumerated if an array is iterated over using for...in. This means for...in does not only iterate over the array elements, it will also iterate over array properties and functions.

The result of this is that the sqlite3InitModule() call will fail, with eg:

ERROR: 'sqlite3 bootstrap initializer threw:', TypeError: xArg.get(...) is not a function
TypeError: xArg.get(...) is not a function
    at Object.cache.xWrap.convertArgNoCheck (./node_modules/@sqlite.org/sqlite-wasm/sqlite-wasm/jswasm/sqlite3-bundler-friendly.mjs:7762:1)
    at Object.sqlite3_vfs_find (./node_modules/@sqlite.org/sqlite-wasm/sqlite-wasm/jswasm/sqlite3-bundler-friendly.mjs:7805:1)
    at ./node_modules/@sqlite.org/sqlite-wasm/sqlite-wasm/jswasm/sqlite3-bundler-friendly.mjs:10451:1
    at ./node_modules/@sqlite.org/sqlite-wasm/sqlite-wasm/jswasm/sqlite3-bundler-friendly.mjs:6782:1
    at Array.forEach (<anonymous>)
    at sqlite3ApiBootstrap (./node_modules/@sqlite.org/sqlite-wasm/sqlite-wasm/jswasm/sqlite3-bundler-friendly.mjs:6781:1)
    at ./node_modules/@sqlite.org/sqlite-wasm/sqlite-wasm/jswasm/sqlite3-bundler-friendly.mjs:14368:1
    at callRuntimeCallbacks (./node_modules/@sqlite.org/sqlite-wasm/sqlite-wasm/jswasm/sqlite3-bundler-friendly.mjs:669:1)
    at postRun (./node_modules/@sqlite.org/sqlite-wasm/sqlite-wasm/jswasm/sqlite3-bundler-friendly.mjs:448:1)
    at doRun (./node_modules/@sqlite.org/sqlite-wasm/sqlite-wasm/jswasm/sqlite3-bundler-friendly.mjs:5664:1)

Due to this for...in loop in /ext/wasm/common/whwasmutil.js on line 2016:

        for(const i in args) args[i] = cxw.convertArgNoCheck(
          argTypes[i], args[i], args, i
        );

Simply replacing this loop with a for(let i=0; i<args.length; i++) loop fixes the issue.

There are other for...in loops in that file, but as far as I can tell they all iterate over objects not arrays, and handle extended prototypes well. In any case the above line is all I needed to change to migrate our application from sql.js to sqlite-wasm.

(2.1) By Stephan Beal (stephan) on 2024-05-09 19:01:00 edited from 2.0 in reply to 1 [link] [source]

By default, Ember will extend the global Array prototype with some helper functions.

Which has (just for the record) long been considered bad practice in JS. e.g.:

https://stackoverflow.com/questions/14034180/why-is-extending-native-objects-a-bad-practice

Note that the page you linked to is specifically about turning off this Ember capability:

However, we understand that there are cases where your Ember.js application may be embedded in an environment beyond your control. The most common scenarios are when authoring third-party JavaScript that is embedded directly in other pages, or when transitioning an application piecemeal to a more modern Ember.js architecture.

In those cases, where you can't or don't want to modify native prototypes, Ember.js allows you to completely disable the extensions described above.

This is arguably one of those cases.

Due to this for...in loop in /ext/wasm/common/whwasmutil.js on line 2016:

Thank you for the report.

That particular loop instance was just patched for the pending 3.46 release and in the 3.45 branch, but we cannot promise to remember to avoid that perfectly legal/conventional looping approach in future code. Nor can we guaranty that Emscripten-generated code (which we have no control over) won't contain such loops.

(3) By Grant Cox (grantcox) on 2024-05-09 19:22:56 in reply to 2.1 [link] [source]

That particular loop instance was just patched for the pending 3.46 release and in the 3.45 branch

Great to hear it!

While I agree that extending prototypes is an antipattern, it is also a "perfectly legal" aspect of the Javascript language. Javascript/Typescript linting tools like ESLint will actually warn about using "for...in", and are perfectly happy with prototype extensions!

(4) By Stephan Beal (stephan) on 2024-05-09 19:25:40 in reply to 3 [link] [source]

Javascript/Typescript linting tools like ESLint will actually warn about using "for...in", and are perfectly happy with prototype extensions!

If they warn about the side-effects, they're not perfectly happy about it ;).

In any case: i will attempt to remember not to use that construct for arrays, for the sake of such side-effects, but can make no promises about future-me's memory!