cubing / cubing.js

🛠 A library for displaying and working with twisty puzzles. Also currently home to the code for Twizzle.
https://js.cubing.net/cubing/
GNU General Public License v3.0
232 stars 42 forks source link

[cubing.js issue] With angular Twisty player cannot load #322

Closed BartaG512 closed 4 months ago

BartaG512 commented 4 months ago

Steps to reproduce the issue

Install cubing js in an angular project I am importing 'cubing/twisty' in a component. The player component is partially loaded.

Observed behaviour

In the browser I am getting these errors

main.ts:5 ERROR TypeError: Cannot read properties of undefined (reading 'playing')
    at TwistyAnimationController.<anonymous> (index.js:169:21)
    at Generator.next (<anonymous>)
    at chunk-IUVSABC3.js?v=5adf3bce:56:61
    at new ZoneAwarePromise (zone.js:1425:21)
    at __async (chunk-IUVSABC3.js?v=5adf3bce:40:10)
    at TwistyAnimationController.onPlayingProp (index.js:168:36)
    at PlayingInfoProp.<anonymous> (chunk-OJEAX4NL.js:118:7)
    at Generator.next (<anonymous>)
    at fulfilled (chunk-IUVSABC3.js?v=5adf3bce:43:24)
    at _ZoneDelegate.invoke (zone.js:368:26)
handleError @ core.mjs:7473
next @ core.mjs:34731
ConsumerObserver2.next @ Subscriber.js:96
Subscriber2._next @ Subscriber.js:63
Subscriber2.next @ Subscriber.js:34
(anonymous) @ Subject.js:41
errorContext @ errorContext.js:19
Subject2.next @ Subject.js:31
emit @ core.mjs:115
(anonymous) @ core.mjs:15639
invoke @ zone.js:368
run @ zone.js:130
runOutsideAngular @ core.mjs:15509
onHandleError @ core.mjs:15639
handleError @ zone.js:372
runGuarded @ zone.js:143
api.microtaskDrainDone @ zone.js:1057
drainMicroTaskQueue @ zone.js:589
Promise.then (async)
nativeScheduleMicroTask @ zone.js:558
scheduleMicroTask @ zone.js:569
scheduleTask @ zone.js:392
onScheduleTask @ core.mjs:15282
scheduleTask @ zone.js:382
onScheduleTask @ zone.js:280
scheduleTask @ zone.js:382
scheduleTask @ zone.js:217
scheduleMicroTask @ zone.js:237
scheduleResolveOrReject @ zone.js:1250
then @ zone.js:1456
runInitializers @ core.mjs:32019
(anonymous) @ core.mjs:34746
_callAndReportToErrorHandler @ core.mjs:32079
(anonymous) @ core.mjs:34744
invoke @ zone.js:368
onInvoke @ core.mjs:15613
invoke @ zone.js:367
run @ zone.js:130
run @ core.mjs:15464
internalCreateApplication @ core.mjs:34721
bootstrapApplication @ platform-browser.mjs:1124
(anonymous) @ main.ts:5
Show 40 more frames
Show less
main.ts:5 ERROR TypeError: Cannot read properties of undefined (reading 'move')
    at TwistyAnimationController.<anonymous> (index.js:175:36)
    at Generator.next (<anonymous>)
    at chunk-IUVSABC3.js?v=5adf3bce:56:61
    at new ZoneAwarePromise (zone.js:1425:21)
    at __async (chunk-IUVSABC3.js?v=5adf3bce:40:10)
    at TwistyAnimationController.onCatchUpMoveProp (index.js:174:40)
    at CatchUpMoveProp.<anonymous> (chunk-OJEAX4NL.js:118:7)
    at Generator.next (<anonymous>)
    at fulfilled (chunk-IUVSABC3.js?v=5adf3bce:43:24)

🖼 Screenshots

image

Expected behaviour

Expect the player to load

Environment

v18.18.2

"@angular/animations": "^17.0.0", "@angular/common": "^17.0.0", "@angular/compiler": "^17.0.0", "@angular/core": "^17.0.0", "@angular/forms": "^17.0.0", "@angular/platform-browser": "^17.0.0", "@angular/platform-browser-dynamic": "^17.0.0", "@angular/router": "^17.0.0", "cubing": "^0.47.1",

Additional info

No response

rokicki commented 4 months ago

Can you give specific steps to reproduce? Don’t assume we program in angular.

On Wed, Feb 21, 2024 at 10:39 AM BartaG512 @.***> wrote:

Steps to reproduce the issue

Install cubing js in an angular project I am importing 'cubing/twisty' in a component. The player component is partially loeaded. Observed behaviour

And in the browser I am getting these errors

main.ts:5 ERROR TypeError: Cannot read properties of undefined (reading 'playing') at TwistyAnimationController. (index.js:169:21) at Generator.next () at chunk-IUVSABC3.js?v=5adf3bce:56:61 at new ZoneAwarePromise (zone.js:1425:21) at __async (chunk-IUVSABC3.js?v=5adf3bce:40:10) at TwistyAnimationController.onPlayingProp (index.js:168:36) at PlayingInfoProp. (chunk-OJEAX4NL.js:118:7) at Generator.next () at fulfilled (chunk-IUVSABC3.js?v=5adf3bce:43:24) at _ZoneDelegate.invoke (zone.js:368:26) handleError @ core.mjs:7473 next @ core.mjs:34731 ConsumerObserver2.next @ Subscriber.js:96 Subscriber2._next @ Subscriber.js:63 Subscriber2.next @ Subscriber.js:34 (anonymous) @ Subject.js:41 errorContext @ errorContext.js:19 Subject2.next @ Subject.js:31 emit @ core.mjs:115 (anonymous) @ core.mjs:15639 invoke @ zone.js:368 run @ zone.js:130 runOutsideAngular @ core.mjs:15509 onHandleError @ core.mjs:15639 handleError @ zone.js:372 runGuarded @ zone.js:143 api.microtaskDrainDone @ zone.js:1057 drainMicroTaskQueue @ zone.js:589 Promise.then (async) nativeScheduleMicroTask @ zone.js:558 scheduleMicroTask @ zone.js:569 scheduleTask @ zone.js:392 onScheduleTask @ core.mjs:15282 scheduleTask @ zone.js:382 onScheduleTask @ zone.js:280 scheduleTask @ zone.js:382 scheduleTask @ zone.js:217 scheduleMicroTask @ zone.js:237 scheduleResolveOrReject @ zone.js:1250 then @ zone.js:1456 runInitializers @ core.mjs:32019 (anonymous) @ core.mjs:34746 _callAndReportToErrorHandler @ core.mjs:32079 (anonymous) @ core.mjs:34744 invoke @ zone.js:368 onInvoke @ core.mjs:15613 invoke @ zone.js:367 run @ zone.js:130 run @ core.mjs:15464 internalCreateApplication @ core.mjs:34721 bootstrapApplication @ platform-browser.mjs:1124 (anonymous) @ main.ts:5 Show 40 more frames Show less main.ts:5 ERROR TypeError: Cannot read properties of undefined (reading 'move') at TwistyAnimationController. (index.js:175:36) at Generator.next () at chunk-IUVSABC3.js?v=5adf3bce:56:61 at new ZoneAwarePromise (zone.js:1425:21) at __async (chunk-IUVSABC3.js?v=5adf3bce:40:10) at TwistyAnimationController.onCatchUpMoveProp (index.js:174:40) at CatchUpMoveProp. (chunk-OJEAX4NL.js:118:7) at Generator.next () at fulfilled (chunk-IUVSABC3.js?v=5adf3bce:43:24)

🖼 Screenshots

image.png (view on web) https://github.com/cubing/cubing.js/assets/28688421/999fb51e-215e-4628-bbbf-c8dafbc5c2ef Expected behaviour

Expect the player to load Environment

v18.18.2

@./animations": "^17.0.0", @./common": "^17.0.0", @./compiler": "^17.0.0", @./core": "^17.0.0", @./forms": "^17.0.0", @./platform-browser": "^17.0.0", @./platform-browser-dynamic": "^17.0.0", @./router": "^17.0.0", "cubing": "^0.47.1", Additional info

No response

— Reply to this email directly, view it on GitHub https://github.com/cubing/cubing.js/issues/322, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAMOLS6JMBMMUS4ILB5YALDYUYIM3AVCNFSM6AAAAABDTJCSZOVHI2DSMVQWIX3LMV43ASLTON2WKOZSGE2DOMBXGAYDKMY . You are receiving this because you are subscribed to this thread.Message ID: @.***>

BartaG512 commented 4 months ago

Ok. I have created an example repository

  1. git clone https://github.com/BartaG512/issue-demo

In the src/app/app.component.ts I import cubing/twisty. In the app.component.html I added the twisty player element.

  1. npm install
  2. npm run start to run developer server
  3. Open up http://localhost:4200 Inspect the page and see the Console in browser.

It is conflicting with zone.js I think

lgarron commented 4 months ago

Thanks for the repro repo!

Unfortunately, when I try to run it in a codespace, http://localhost:4200/ hangs indefinitely instead of ever serving anything. Do you know why that might be happening?

BartaG512 commented 4 months ago

Can you open it in stackblitz? https://stackblitz.com/~/github.com/BartaG512/issue-demo

lgarron commented 4 months ago

Can you open it in stackblitz? https://stackblitz.com/~/github.com/BartaG512/issue-demo

I'm able to see the repro there, thanks!

Unfortunately, the error is obfuscated by a lot of code that Angular injects into the stack. It looks like this has something to do with "zones": https://angular.io/guide/zone

Given that this is a completely non-standard and proprietary concept that seems to break the semantics of vanilla JavaScript, I don't know if I'll be able to get to the bottom of this.

If you're not particularly set on Angular, I'd suggest a light-weight setup based on esbuild using https://github.com/cubing/create-cubing-app

lgarron commented 4 months ago

Unfortunately, the error is obfuscated by a lot of code that Angular injects into the stack. It looks like this has something to do with "zones": https://angular.io/guide/zone

Given that this is a completely non-standard and proprietary concept that seems to break the semantics of vanilla JavaScript, I don't know if I'll be able to get to the bottom of this.

Just to demonstrate the scope of this: Screenshot 2024-02-29 at 19 13 05

That's 23 stack frames of code injected between cubing.js functions. 😳

EDIT: I actually missed a few — queue and some lower stack frames are from cubing.js.

BartaG512 commented 4 months ago

Can you open it in stackblitz? https://stackblitz.com/~/github.com/BartaG512/issue-demo

I'm able to see the repro there, thanks!

Unfortunately, the error is obfuscated by a lot of code that Angular injects into the stack. It looks like this has something to do with "zones": https://angular.io/guide/zone

Given that this is a completely non-standard and proprietary concept that seems to break the semantics of vanilla JavaScript, I don't know if I'll be able to get to the bottom of this.

If you're not particularly set on Angular, I'd suggest a light-weight setup based on esbuild using https://github.com/cubing/create-cubing-app

I decided to wrap it in an iframe to separate it from angular context.

lgarron commented 4 months ago

I decided to wrap it in an iframe to separate it from angular context.

That would certainly work, but keep in mind that will result in additional overhead. You may also run out of WebGL contexts very quickly if you include multiple frames. 😔

In any case, I took a look at disabling zone.js, and Angular throws this error without further help:

NG0908: In this configuration Angular requires Zone.js

I'm going to poke at this a bit more, but I can't promise any results.

lgarron commented 4 months ago

I dug into this for about an hour and my conclusion is that the way Angular is rewriting Promises for its zones is completely broken. 😕

From https://github.com/angular/angular/issues/31730#issuecomment-1765982586 :

Since v15, Angular forces ES2022 but uses babel-plugin-transform-async-to-promises to convert async/await to promises. (zone.js cannot patch await). This is still true even when using the noop-zone cf https://github.com/angular/angular-cli/issues/22191

This exactly resembles the issue you're encountering, where one of our async function has been rewritten into a generator but the yield expression sometimes evaluates to undefined:

Screenshot 2024-02-29 at 20 49 20

It looks like this has been an issue since async/await became standard almost 7 years ago, and all the simple workarounds for Angular have stalled in the meantime. I can sympathize with the Angular maintainers for being in a sub-optimal situation, but this is not something we can work around in cubing.js.

https://github.com/angular/angular-cli/issues/22191 looks like the best hope, you may want to try supporting that.

It is of course your choice if you want to use Angular, but at this point I would unfortunately strongly recommend against it.