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

Can't seem to load browser friendly parser #47

Closed
Janther opened this issue Jun 18, 2021 · 16 comments · Fixed by #106
Closed

Can't seem to load browser friendly parser #47

Janther opened this issue Jun 18, 2021 · 16 comments · Fixed by #106

Comments

@Janther
Copy link
Collaborator

Janther commented Jun 18, 2021

If trying to load the browser friendly parser I get an empty object.

const parser = require('@solidity-parser/parser');
console.log(parser) // { ParserError: [Getter], parse: [Getter], tokenize: [Getter], visit: [Getter] } 

const parser = require('@solidity-parser/parser/dist/index.iife');
console.log(parser) // {}
@Janther
Copy link
Collaborator Author

Janther commented Jun 18, 2021

If I load it as it's own file I have access to window.SolidityParser but that would mean that I'd have to override the prettier-solidity-plugin behaviour, I made it work but it does look like a hack.

@Janther
Copy link
Collaborator Author

Janther commented Jun 22, 2021

after some battling with this, I was able to make this work in a not too hacky way.

// We tell webpack to use the browser friendly package.
wepackConfig.resolve.alias["@solidity-parser/parser"] = "@solidity-parser/parser/dist/index.iife.js";
wepackConfig.module.rules = [
  {
    // We tell webpack to append "module.exports = SolidityParser;" at the end of the file.
    test: require.resolve("@solidity-parser/parser/dist/index.iife.js"),
    loader: "exports-loader",
    options: {
      type: "commonjs",
      exports: "single SolidityParser",
    },
  },
  ...wepackConfig.module.rules
];
if (isEnvDevelopment) {
  // Had some issues on development server with this strategy but works on production.
  wepackConfig.module.noParse = /@solidity-parser\/parser/;
}

@fvictorio
Copy link
Contributor

Ideally the browser output would be UMD instead of an IIFE, but sadly esbuild doesn't support UMD yet: evanw/esbuild#507 There seems to be an ugly workaround: evanw/esbuild#507 (comment)

@aquiladev
Copy link

any updates so far?

@fvictorio
Copy link
Contributor

@aquiladev sorry, no. I think there are some manual shenanigans that I could do; if this is blocking something important for you I can try to do it one of these days.

@aquiladev
Copy link

aquiladev commented Sep 3, 2021

the issue crashed remix sol2uml plugin, I'm thinking to revert it to previous version

@fvictorio
Copy link
Contributor

@aquiladev Oh, that sucks. Are you on telegram? Can you DM me?

@ulasanil
Copy link

I am working on a project that runs purely on browser and I wasn't able to load this package. With a little bit of debugging I found the following code was the cause of the problem in src/tokens-string.js:

if (typeof BROWSER !== "undefined") {
  module.exports = require('./antlr/Solidity.tokens')
} else {
  module.exports = require('fs')
    .readFileSync(require('path').join(__dirname, './antlr/Solidity.tokens'))
    .toString()
}

For some reason, BROWSER variable is always undefined and this causes problems on the bundler side because there is no fs module on browser. So what I did was to replace BROWSER with window object to detect if the package is running in the browsers context:

if (typeof window !== "undefined") {
  module.exports = require('./antlr/Solidity.tokens')
} else {
  module.exports = require('fs')
    .readFileSync(require('path').join(__dirname, './antlr/Solidity.tokens'))
    .toString()
}

With this change, everything worked flawlessly. Now I need to mention that I am pretty new to whole Typescript, bundler stuff so maybe what I did was unnecessary or unrelated to the issue raised here. But still, I wanted to share it here in case it might help someone.

@FrozenKiwi
Copy link

FrozenKiwi commented Nov 23, 2022

In webpack (>5?) you can skip the fs check by:

  resolve: {
    fallback: {
      "fs": false,
      "path": false,
    }
  }

You can also get past (typeof BROWSER !== "undefined") without editing the src by using Webpack DefinePlugin

   ...
  plugins: [
    new webpack.DefinePlugin({
      BROWSER: true,
    }),

@tonisives
Copy link

I also have this problem in AWS lambda environment

{
  "errorType": "Error",
  "errorMessage": "ENOENT: no such file or directory, open '/var/task/antlr/Solidity.tokens'",
  "trace": [
    "Error: ENOENT: no such file or directory, open '/var/task/antlr/Solidity.tokens'",
    "    at Object.openSync (node:fs:585:3)",
    "    at Object.readFileSync (node:fs:453:35)",
    "    at /var/task/app.js:65:22368",
    "    at /var/task/app.js:34:14107",
    "    at /var/task/app.js:276:98592",
    "    at /var/task/app.js:1:222",
    "    at Object.<anonymous> (/var/task/app.js:277:2424)",
    "    at Module._compile (node:internal/modules/cjs/loader:1105:14)",
    "    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1159:10)",
    "    at Module.load (node:internal/modules/cjs/loader:981:32)"
  ]
}
FindingsApi:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: src/finding/
      Handler: app.lambdaHandler
      
      Runtime: nodejs16.x
      Architectures:
        - x86_64
      Events:
        Finding:
          Type: Api
          Properties:
            Path: /finding
            Method: ANY
      Policies:
        - AmazonDynamoDBFullAccess
        - AmazonSESFullAccess
      AutoPublishAlias: live
    Metadata:
      BuildMethod: esbuild
      BuildProperties:
        Minify: true
        Target: "es2020"
        EntryPoints:
          - app.ts

@Janther
Copy link
Collaborator Author

Janther commented Jan 12, 2023

I also have this problem in AWS lambda environment

this is how remix-project loads it.
at some point they load @solidity-parser/parser/dist/index.iife.js and the call the global variable SolidityParser we use a similar strategy in prettier-plugin-solidity but we automated at the webpack configuration.

// use the parser already included in the app
const parser = (window as any).SolidityParser

@tonisives
Copy link

AWS Lambda is not a browser environment, therefore window is not defined. I tried to load the iife file from node modules, but it returned an empty SolidityParser object.

In the end, I included the antlr folder in my uploaded zip file. I needed to configure my build so this folder is copied.

Then the Lambda structure looked like this:
Screenshot 2023-01-14 at 16 01 33

@Janther
Copy link
Collaborator Author

Janther commented Jan 14, 2023

AWS Lambda is not a browser environment, therefore window is not defined.

could you have used global or this instead of window? I'm not familiar with AWS Lambda. but if that solved your issue then it's ok.

@hananbeer
Copy link

after some battling with this, I was able to make this work in a not too hacky way.

// We tell webpack to use the browser friendly package.
wepackConfig.resolve.alias["@solidity-parser/parser"] = "@solidity-parser/parser/dist/index.iife.js";
wepackConfig.module.rules = [
  {
    // We tell webpack to append "module.exports = SolidityParser;" at the end of the file.
    test: require.resolve("@solidity-parser/parser/dist/index.iife.js"),
    loader: "exports-loader",
    options: {
      type: "commonjs",
      exports: "single SolidityParser",
    },
  },
  ...wepackConfig.module.rules
];
if (isEnvDevelopment) {
  // Had some issues on development server with this strategy but works on production.
  wepackConfig.module.noParse = /@solidity-parser\/parser/;
}

thank you! this worked perfectly for me.

should this be considered the official solution? imo the README should reflect this.

@Janther
Copy link
Collaborator Author

Janther commented Jan 15, 2024

Hi @hananbeer,

now that I've been more involved with this codebase and started actively improving it, I will see what I can do to improve and fix this one thing so no extra Webpack configuration should be necessary.

@hananbeer
Copy link

hananbeer commented Jan 15, 2024

Hi @hananbeer,

now that I've been more involved with this codebase and started actively improving it, I will see what I can do to improve and fix this one thing so no extra Webpack configuration should be necessary.

setting format: 'esm' instead of format: 'iife' in ./scripts/build-browser.js seems to work for me.
while it complains about "no default" I can indeed import { parse } and it works.

although it isn't iife, it works in browser. I'm not sure what the implications are. I think if someone wants to use iife then they won't have the import issue to begin with.

edit: I see now you committed a UMD version, whatever that is. JS-soup. 🤷

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

Successfully merging a pull request may close this issue.

7 participants