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

Build fails with latest Angular #3910

Closed
imaksp opened this issue Mar 17, 2023 · 33 comments
Closed

Build fails with latest Angular #3910

imaksp opened this issue Mar 17, 2023 · 33 comments
Assignees
Labels
fixed/complete This Bug is fixed or Enhancement is complete and published. v6 Issues regarding v6

Comments

@imaksp
Copy link

imaksp commented Mar 17, 2023

Ethers Version

6.1.0

Search Terms

angular

Describe the Problem

Typescript shows this error when compiling:

Error: node_modules/ethers/types/providers/provider-ipcsocket.d.ts:1:23 - error TS1452: 'resolution-mode' assertions are only supported when `moduleResolution` is `node16` or `nodenext`.

1 /// <reference types="node" resolution-mode="require"/>

moduleResolution node16 or nodenext are not working with official angular setup & node is currently a default for new angular project.
& due to this error build command is failing.

& as a workaround I have added "skipLibCheck": true in tsconfig.

Code Snippet

No response

Contract ABI

No response

Errors

No response

Environment

node.js (v12 or newer)

Environment (Other)

Angular CLI

@imaksp imaksp added investigate Under investigation and may be a bug. v6 Issues regarding v6 labels Mar 17, 2023
@imaksp
Copy link
Author

imaksp commented Mar 18, 2023

It seems issue is more serious than I thought. Adding a skipLibCheck fixes the error but after that app does not work as expected, any attempt to communicate with Metamask wallet using BrowserProvider fails with an error like this:

app.component.ts:41 ERROR Error: Uncaught (in promise): TypeError: Cannot read properties of undefined (reading '_getOption')
TypeError: Cannot read properties of undefined (reading '_getOption')
    at provider-jsonrpc.js:346:30
    at Generator.next (<anonymous>)
    at asyncGeneratorStep (asyncToGenerator.js:3:1)
    at _next (asyncToGenerator.js:22:1)
    at asyncToGenerator.js:27:1
    at new ZoneAwarePromise (zone.js:1432:21)

You can use following repo to regenerate the issue:
https://github.com/aksdevac/test-ethers-v6-angular#steps-to-regenerate

@ricmoo
Copy link
Member

ricmoo commented Mar 18, 2023

It doesn't look like ethers is in your package-lock.json?

@ricmoo
Copy link
Member

ricmoo commented Mar 18, 2023

I also generally do not install an execute repos on my machine. Could you possibly include minimal reproduction steps using standard (well-known) CLI steps?

@imaksp
Copy link
Author

imaksp commented Mar 20, 2023

Sure, here are the steps:

  • Install Angular CLI: npm install -g @angular/cli
  • Generate new app using: ng new ethers-test-app
  • Run yarn/npm start to see if app is working
  • install ethers yarn add ethers or npm i ethers & import ethers lib in app.component.ts
  • Run yarn/npm start again to see compile error due to ethers import
  • Replace the content of app.component.ts & app.component.html with content in sample repo https://github.com/aksdevac/test-ethers-v6-angular/tree/main/src/app
  • Add skipLibCheck true in tsconfig.json to get rid off compile error
  • Run app again & click on Connect button to see the error.

& ethers is not in package lock because I installed it using yarn, forgot to add package-lock in .gitignore.

@ricmoo ricmoo added the on-deck This Enhancement or Bug is currently being worked on. label Mar 20, 2023
@marshalys
Copy link

marshalys commented Mar 22, 2023

@ricmoo
Copy link
Member

ricmoo commented Mar 22, 2023

I think your link is missing the filename?

@marshalys
Copy link

I think your link is missing the filename?

I'm sorry. link is https://github.com/ethers-io/ethers.js/blob/main/types/providers/provider-ipcsocket.d.ts#L1

@ricmoo
Copy link
Member

ricmoo commented Mar 22, 2023

Weird. I’m not even sure why it injects that line. The other .d.ts files don’t seem to have that; perhaps due to the net package? I’ll look into this.

@marshalys
Copy link

Weird. I’m not even sure why it injects that line. The other .d.ts files don’t seem to have that; perhaps due to the net package? I’ll look into this.

because this module use lib "net" which is belong node lib

@ricmoo
Copy link
Member

ricmoo commented Mar 24, 2023

I can reproduce it and have been looking at it for a few hours now. It looks like the asyncToGenerator is dereferencing the method, so it is no longer bound to the object. Still looking into it, just keeping you in the loop. Let me know if you figure anything out too. :)

@ricmoo
Copy link
Member

ricmoo commented Mar 24, 2023

(oh, and I didn't need to add skipLibCheck; the only changes I made to the default package was changing the tsconfig "moduleResolution": "node16" and adding "type": "module" to the package.json ;))

@ricmoo
Copy link
Member

ricmoo commented Mar 24, 2023

FYI; seems related to this issue.

@ricmoo
Copy link
Member

ricmoo commented Mar 24, 2023

I think I've found the code in ethers that is causing issues. If so, it is definitely a compiler bug in Angular which could be addressed by updating the version of Babel (I think).

Here is the code in ethers which is totally valid, but it uses this inside an arrow function, which the old-version Babel compiler bug drops (making the this undefined).

I'm a bit apprehensive about this change, since I'm sure there are plenty of places I use this pattern (as it is valid and really the entire reason for arrow functions).

Is it easy to update the babel compiler within Angular? I'm still investigating, but this is what I've found so far.

@imaksp
Copy link
Author

imaksp commented Mar 24, 2023

Ok but is this solution requires changing resolution to node16 or nodenext if yes angular might not fix quickly as by default they use module resolution node, but still I can create an issue with Angular.

@ricmoo
Copy link
Member

ricmoo commented Mar 24, 2023

Oh, the node16 just gets rid of the warning re: reference types="blah" and the "type": "module" gets rid of the commonjs warning. Those are just warnings, so I'm not worried about them.

Those are separate from the this._getOptions problem.

When I looked at the package-lock they use all sorts of old versions of babel across their dependencies. It might just be a matter of updating whichever dependency is responsible for the asyncToGenerator compiler. I'm not exactly sure where that is yet.

I don't really understand how this isn't a larger problem for them; surely ethers can't be the only library that uses arrow functions inside a method? :p

@imaksp
Copy link
Author

imaksp commented Mar 24, 2023

If you are talking about this babel issue , then it seems it was fixed & angular is using newer version than required, these are the currently resolved versions:

babel-version

@ricmoo
Copy link
Member

ricmoo commented Mar 24, 2023

That version is still 3 months old, but it is likely fine. But if you look through the entire lock file, there are some places that specify a 5 year old (!!) version of babel. I'm not sure which dependency it pulls asyncToGenerator from, and that is the dependency to keep an eye on.

Tomorrow I will make a few small changes locally to verify that is the problem and will also create a smaller proof-of-concept to demonstrate if it is the problem.

I don't know Angular, so I'm just reading through their code as best I can.

@imaksp
Copy link
Author

imaksp commented Mar 24, 2023

FYI: I just tried it with next angular version (v16) which uses latest babel (7.21.3), & it still gives same (_getOption) error. I am attaching its package lock file for reference.
& you can generate it by installing angular cli using npm i -g @angular/cli@next.

package-lock.json.zip

@ricmoo
Copy link
Member

ricmoo commented Mar 24, 2023

Thanks. I’ll try more things out tomorrow.

@marshalys
Copy link

If we set resolution-mode="require" in d.ts file, it force typescrtpt project witch use this lib must set moduleResolution from node to node16 or nodenext in their tsconfig file. otherwise it will build fail.
It's not good and not necessary.
Bacause if you change moduleResolution from node to node16 in a typescript project, you must change import code: relative import paths need full extensions (we have to write import "./foo.js" instead of import "./foo")

@imaksp
Copy link
Author

imaksp commented Mar 24, 2023

Hi @marshalys yes but It is less serious issue, & can be fixed by adding skipLibCheck: true , currently default NextJS project also sets skipLibCheck to true by default (& ethers v6 works without issues for it), but angular doesn't set it so it gives compile error, but still its nice to have.

& currently in NextJS too if I set skipLibCheck to false & use ethers v6 then next build is failing (but with different error which I have not checked in detail as its less serious issue & its already set to false in default next tsconfig.).

But currently the main issue is it is not working in Angular even with skipLibCheck: false due to some babel async generator related issue.
Let us know if you have any inputs regarding the this babel issue.

@marshalys
Copy link

Weird, I didn't get the error. It look fine.
I use
npm install
npm start

Sure, here are the steps:

  • Install Angular CLI: npm install -g @angular/cli
  • Generate new app using: ng new ethers-test-app
  • Run yarn/npm start to see if app is working
  • install ethers yarn add ethers or npm i ethers & import ethers lib in app.component.ts
  • Run yarn/npm start again to see compile error due to ethers import
  • Replace the content of app.component.ts & app.component.html with content in sample repo https://github.com/aksdevac/test-ethers-v6-angular/tree/main/src/app
  • Add skipLibCheck true in tsconfig.json to get rid off compile error
  • Run app again & click on Connect button to see the error.

& ethers is not in package lock because I installed it using yarn, forgot to add package-lock in .gitignore.

@imaksp
Copy link
Author

imaksp commented Mar 25, 2023

Weird, I didn't get the error. It look fine. I use npm install npm start

Ok that's surprising do you see Network after you click Connect button?

@marshalys
Copy link

Weird, I didn't get the error. It look fine. I use npm install npm start

Ok that's surprising do you see Network after you click Connect button?

Is this UI right?
CleanShot 2023-03-26 at 08 14 35@2x

@imaksp
Copy link
Author

imaksp commented Mar 26, 2023

@marshalys yes it should display network after you allow wallet access, but it gives error, request accounts is called directly on ethereum object ethers is not used for this.

@imaksp
Copy link
Author

imaksp commented Mar 27, 2023

Hi @ricmoo I have tried to narrow down the issue & found that it is related to some babel transform issue based on browser target if I target last 2 Chrome versions, last 2 Safari major versions (Safari 15+) if produces more complex non working code without private class field
& if I target last 2 Chrome versions, last 1 Safari major versions (Safari 16+) it generates working code by using private class field.
Here is working & non working JsonRpcApiProvider class with only _detectNetwork function:

class Working {
  _detectNetwork() {
    var e = this;
    return m(function* () {
      const n = e._getOption("staticNetwork");
      if (n) return n;
      if (e.ready) return Kt.from(R(yield e.send("eth_chainId", [])));
      const r = {
        id: e.#t++,
        method: "eth_chainId",
        params: [],
        jsonrpc: "2.0",
      };
      let s;
      e.emit("debug", {
        action: "sendRpcPayload",
        payload: r,
      });
      try {
        s = (yield e._send(r))[0];
      } catch (i) {
        throw (
          (e.emit("debug", {
            action: "receiveRpcError",
            error: i,
          }),
          i)
        );
      }
      if (
        (e.emit("debug", {
          action: "receiveRpcResult",
          result: s,
        }),
        "result" in s)
      )
        return Kt.from(R(s.result));
      throw e.getRpcError(r, s);
    })();
  }
}

class NonWorking {
  _detectNetwork() {
    return w(function* () {
      var e,
        n,
        r = this;
      const i = r._getOption("staticNetwork");
      if (i) return i;
      if (r.ready) return sn.from(B(yield r.send("eth_chainId", [])));
      const s = {
        id: (y(r, ao, ((e = p(r, ao)), (n = e++), e)), n),
        method: "eth_chainId",
        params: [],
        jsonrpc: "2.0",
      };
      let o;
      r.emit("debug", {
        action: "sendRpcPayload",
        payload: s,
      });
      try {
        o = (yield r._send(s))[0];
      } catch (a) {
        throw (
          (r.emit("debug", {
            action: "receiveRpcError",
            error: a,
          }),
          a)
        );
      }
      if (
        (r.emit("debug", {
          action: "receiveRpcResult",
          result: o,
        }),
        "result" in o)
      )
        return sn.from(B(o.result));
      throw r.getRpcError(s, o);
    })();
  }
}

In non working class this & var e, n & r will be undefined.

If you can find the root cause then it would be possible to file an issue with Babel.

& for now I have fixed it by targeting only latest browsers & adding skipLibCheck false. (because we are only using ethers only for admin app so can target only newer browsers)

@ambersun1234
Copy link

Same with ethers 6.3.0 and angular 15.2.6

@ricmoo
Copy link
Member

ricmoo commented Apr 28, 2023

FYI, there is now an Angular environment CI test, thanks to your work. So, the CI will fail if there are any future issues building an Angular app.

See: https://github.com/ethers-io/ethers.js/blob/main/.github/workflows/test-env.yml#L56

Thanks! :)

@ricmoo
Copy link
Member

ricmoo commented Jun 6, 2023

I believe this is now working, so I’ll close it again. Please re-open if it is still an issue.

@ricmoo ricmoo closed this as completed Jun 6, 2023
@ricmoo ricmoo added fixed/complete This Bug is fixed or Enhancement is complete and published. and removed on-deck This Enhancement or Bug is currently being worked on. labels Jun 6, 2023
@imaksp
Copy link
Author

imaksp commented Jun 6, 2023

Hi @ricmoo only build error issue is fixed which was minor (can also be fixed by adding skipLibCheck in tsconfig), but actual error due to incorrect babel transform is still present (TypeError: Cannot read properties of undefined (reading '_getOption')).
so currently it is not possible to use ethers v6 in Angular with default setup/browserlists
Here is updated demo repo with Angular 16 & standalone api.
https://github.com/imaksp/test-ethers-v6-angular

You can trust this repo, or you can also create new project using ng new test-ethers-v6-angular --standalone & then replace content of app.component.html & app.component.ts files.

& see my previous comment for details (which has Working & NonWorking sample babel output for _detectNetwork function)

@imaksp
Copy link
Author

imaksp commented Jun 6, 2023

Just checked with new builder & surprisingly it worked (esbuild based builder - which is currently in developer preview),
& mostly it is not using babel based transform so it worked.
so for me it is now low priority issue. Thanks.

@ricmoo ricmoo removed the investigate Under investigation and may be a bug. label Jun 8, 2023
@hans-crypto
Copy link

But unfortunately this builder is not yet released for productive use. For instance, it does not yet support the internationalization (i18n) feature of Angular.

@imaksp
Copy link
Author

imaksp commented Jun 23, 2023

But unfortunately this builder is not yet released for productive use. For instance, it does not yet support the internationalization (i18n) feature of Angular.

If you have to use webpack based builder due to some custom config, you can try by targeting only latest browsers by adding browserslist or you can also try rspack based builder (unofficial), they are actively working on Angular support.

& this is issue is related to babel but to create an issue with babel someone needs to narrow down further. as we have switched to new esbuild based builder I am not looking into now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fixed/complete This Bug is fixed or Enhancement is complete and published. v6 Issues regarding v6
Projects
None yet
Development

No branches or pull requests

5 participants