Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot set property 'exports' of undefined #406

Open
amura11 opened this issue Jun 24, 2020 · 16 comments
Open

Cannot set property 'exports' of undefined #406

amura11 opened this issue Jun 24, 2020 · 16 comments

Comments

@amura11
Copy link

amura11 commented Jun 24, 2020

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();
@kaizhu256
Copy link
Member

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();

@amura11
Copy link
Author

amura11 commented Jun 24, 2020

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({

@kaizhu256
Copy link
Member

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.

@amura11
Copy link
Author

amura11 commented Jun 25, 2020

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 😵

@megahertz
Copy link

megahertz commented Jun 26, 2020

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.

@hebronivy
Copy link

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.

@kekeqy
Copy link

kekeqy commented Sep 7, 2020

I have the same porblem too.

@gz-95
Copy link

gz-95 commented Sep 8, 2020

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$/,
  },
}

@kekeqy
Copy link

kekeqy commented Sep 8, 2020

module: {
noParse: /sql.js/
}

@lovasoa
Copy link
Member

lovasoa commented Sep 8, 2020

Did you report this bug to webpack ?

@rishabbhattacharyya
Copy link

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)

@maribelmai
Copy link

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

@mcorrigan
Copy link

mcorrigan commented Feb 17, 2023

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'}
      ],
    }),
  ],

@kekeqy
Copy link

kekeqy commented Feb 17, 2023 via email

@SamStenner
Copy link

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

@kekeqy
Copy link

kekeqy commented Apr 3, 2023 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests