sql.js icon indicating copy to clipboard operation
sql.js copied to clipboard

Cannot set property 'exports' of undefined

Open amura11 opened this issue 4 years ago • 16 comments

I'm trying to get Sql.js working with TypeORM inside Electron as part of the renderer but I'm running into an error I don't know how to handle. I'm getting the error: TypeError: Cannot set property 'exports' of undefined. I'm not sure if this is a configuration issue on my end or if there's some sort of bug. It seems like the error happens somewhere in initSqlJs before it gets to locating the wasm binary.

My setup is as follows:

WebPack Config

module.exports = {
    entry: {main: './main.ts'},
    output: {/*Removed for brevity*/},
    target: 'electron-renderer',
    module: {/*Removed for brevity*/},
    plugins: [
        /*Other plugins removed for brevity*/
        new Webpack.NormalModuleReplacementPlugin(/typeorm$/, function (result) {
            result.request = result.request.replace(/typeorm/, "typeorm/browser");
        }),
        new Webpack.ProvidePlugin({
            'window.SQL': 'sql.js/dist/sql-wasm.js'
        }),
        new CopyPlguin({
            patterns: [
                {from: './node_modules/sql.js/dist/sql-wasm.wasm'}
            ]
        })
    ]
}

Main Code

const initSqlJs = require('sql.js');

const SQL = await initSqlJs({
	locateFile: (file: any) => {
		console.log(file); //This line is never printed
		return `https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.1.0/dist/${file}`}
});

var db = new SQL.Database();

amura11 avatar Jun 24 '20 19:06 amura11

likely either in webpack or sqljs, the statement module.exports = ... is failing (because module is null).

if you change your code to the following, you can figure out where the problem is:

+console.log("webpack module.exports is ok");
 const initSqlJs = require('sql.js');
+console.log("sqljs module.exports is ok");

 const SQL = await initSqlJs({
 	locateFile: (file: any) => {
 		console.log(file); //This line is never printed
 		return `https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.1.0/dist/${file}`}
 });

 var db = new SQL.Database();

kaizhu256 avatar Jun 24 '20 19:06 kaizhu256

Hey @kaizhu256, thanks for the suggestion. I tried putting the logging statements and they both work fine (which is confusing and annoying). I checked the stack trace of the error and I'm seeing the error when I call initSqlJs, specifically this line:

const SQL = await initSqlJs({

amura11 avatar Jun 24 '20 21:06 amura11

searching thru the source code, the only place where module.exports is assigned (besides tests) is here. but that happens during the require-call which succeeded, not initSqljs.

so i'm stumped as well.

kaizhu256 avatar Jun 25 '20 02:06 kaizhu256

After doing some more digging I'm even more confused. The error was coming from sql-asm-debug.js at line 1213, looking at the source in the Electron devs tools, I see the following block:

 if (true) {
    module['exports'] = Module;
  }

Which is weird, so I checked the original file in the dist folder and the block at that line is:

  if (typeof module !== 'undefined') {
    module['exports'] = Module;
  }

The latter block makes perfect sense, this is what I'd expect. The first block is really strange but it does explain why my code is failing. For whatever reason module is undefined at that point and would cause the error I'm getting. My guess is this is some sort of optimization that WebPack is performing on code that it bundles. However, what I don't understand is why the optimized (or whatever it would be considered) code is changing the meaning of the if statement and why module is undefined.

On a semi-related note, I originally was testing this code with source maps enabled, which would show the latter block of code but behind the scenes it must have actually been running the first block of code. So while debugging I was seeing the code enter the if statement despite the fact that the expression evaluated to false. I was starting to question everything I knew about software development 😵

amura11 avatar Jun 25 '20 04:06 amura11

The same issue.

Quick and dirty workaround which works for my project:

  • Set SINGLE_FILE=1 in Makefile
  • Comment module = undefined; in shell-pre.js

Than I recompilled sql.js and imported the single sql-wasm.js to the project.

megahertz avatar Jun 26 '20 10:06 megahertz

I have the same problem when call initSqlJs(). enviroment: electron: ^9.0.0 a react project created by CRA image But the code works well in chrome browser.

hebronivy avatar Jul 23 '20 13:07 hebronivy

I have the same porblem too.

kekeqy avatar Sep 07 '20 05:09 kekeqy

I just ran into this problem as well. Comment by @amura11 pretty much nailed the issue with Webpack trying to be smart by statically optimize if (typeof module !== 'undefined') { ... } into if (true) { ... } at compile time. This issue was then further obfuscated by the presence of sourcemaps.

In my Webpack config, I added the following lines to bundle sql.js without extra preprocessing:

{
  module: {
    noParse: /node_modules\/sql\.js\/dist\/sql-wasm\.js$/,
  },
}

gz-95 avatar Sep 08 '20 03:09 gz-95

module: { noParse: /sql.js/ }

kekeqy avatar Sep 08 '20 04:09 kekeqy

Did you report this bug to webpack ?

lovasoa avatar Sep 08 '20 07:09 lovasoa

the issue is still persisting

Uncaught (in promise) TypeError: Cannot set property 'exports' of undefined at index.js:106 at new Promise () at n.r [as sqlite] (index.js:106) at n. (SqljsDriver.js:273) at tslib.es6.js:99 at Object.next (tslib.es6.js:80) at tslib.es6.js:73 at new Promise () at Object.o (tslib.es6.js:69) at n.createDatabaseConnectionWithImport (SqljsDriver.js:263)

rishabbhattacharyya avatar Sep 17 '20 02:09 rishabbhattacharyya

I’m still experiencing this issue. Any update / workaround ?

maribelmai avatar Dec 12 '22 04:12 maribelmai

Oh man, I finally got this working. Turned out to be a few things that made it work. First, I had to do what @kekeqy suggested:

module: {
    noParse: /sql.js/
}

Then I also had to add the wasm directly to my output directory:

plugins: [
    new CopyPlugin({
      patterns: [
        {from: './node_modules/sql.js/dist/sql-wasm.wasm'}
      ],
    }),
  ],

mcorrigan avatar Feb 17 '23 17:02 mcorrigan

这是一封自动回复邮件。已经收到您的来信,我会尽快回复。

kekeqy avatar Feb 17 '23 17:02 kekeqy

I just ran into this problem as well. Comment by @amura11 pretty much nailed the issue with Webpack trying to be smart by statically optimize if (typeof module !== 'undefined') { ... } into if (true) { ... } at compile time. This issue was then further obfuscated by the presence of sourcemaps.

In my Webpack config, I added the following lines to bundle sql.js without extra preprocessing:

{
  module: {
    noParse: /node_modules\/sql\.js\/dist\/sql-wasm\.js$/,
  },
}

I owe you a beer

SamStenner avatar Apr 03 '23 19:04 SamStenner

这是一封自动回复邮件。已经收到您的来信,我会尽快回复。

kekeqy avatar Apr 03 '23 19:04 kekeqy