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

Preserve global context with clock methods (setTimeout/clearTimeout) #1704

Merged
merged 4 commits into from
Dec 7, 2020

Conversation

blimmer
Copy link
Contributor

@blimmer blimmer commented Dec 7, 2020

Fixes #1703

@changeset-bot
Copy link

changeset-bot bot commented Dec 7, 2020

🦋 Changeset detected

Latest commit: 6f7ba59

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
xstate Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@blimmer
Copy link
Contributor Author

blimmer commented Dec 7, 2020

By the way, I just confirmed this fix by using patch-package with the following patchfile for my WebExtension project:

diff --git a/node_modules/xstate/es/interpreter.js b/node_modules/xstate/es/interpreter.js
index a35ec06..8c7fedf 100644
--- a/node_modules/xstate/es/interpreter.js
+++ b/node_modules/xstate/es/interpreter.js
@@ -1237,10 +1237,10 @@ function () {
       deferEvents: true,
       clock: {
         setTimeout: function (fn, ms) {
-          return global.setTimeout.call(null, fn, ms);
+          return global.setTimeout.call(global, fn, ms);
         },
         clearTimeout: function (id) {
-          return global.clearTimeout.call(null, id);
+          return global.clearTimeout.call(global, id);
         }
       },
       logger: global.console.log.bind(console),
diff --git a/node_modules/xstate/lib/interpreter.js b/node_modules/xstate/lib/interpreter.js
index 8216933..64213c7 100644
--- a/node_modules/xstate/lib/interpreter.js
+++ b/node_modules/xstate/lib/interpreter.js
@@ -1039,10 +1039,10 @@ var Interpreter = /** @class */ (function () {
         deferEvents: true,
         clock: {
             setTimeout: function (fn, ms) {
-                return global.setTimeout.call(null, fn, ms);
+                return global.setTimeout.call(global, fn, ms);
             },
             clearTimeout: function (id) {
-                return global.clearTimeout.call(null, id);
+                return global.clearTimeout.call(global, id);
             }
         },
         logger: global.console.log.bind(console),

Firefox now works and Chrome still works with the change.

Copy link
Member

@Andarist Andarist left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem fixed by using global. etc was probably very similar to what you have experienced - before the fix the this has been changed because setTimeout and clearTimeout were attached to another object and they were used from there (oh, our beautiful JS). See the previous version here: 66c8cf2#diff-5b8880ef88d507d13e4d97365bcfbafe3a9d36a16655ef655f51c1c38ab01bb7L108

We don't do any hoops though with global, call etc if we just invoke them using the global context (like in my suggested changes). This way they will be always looked up on a global object and the invocation context will be correct.

If RxJS is using those timers as is (without hoops) I bet that we can do that as well 😉 :
https://github.com/ReactiveX/rxjs/blob/cfa267bc0916ede09c8b14aedcdb69a791055fb6/src/internal/scheduler/timeoutProvider.ts#L21

packages/core/src/interpreter.ts Outdated Show resolved Hide resolved
packages/core/src/interpreter.ts Outdated Show resolved Hide resolved
@blimmer
Copy link
Contributor Author

blimmer commented Dec 7, 2020

I'm happy to do this whichever way is most preferable. @davidkpiano, what do you think?

@Andarist
Copy link
Member

Andarist commented Dec 7, 2020

Could you try the proposed changes with patch-package on your project?

@davidkpiano
Copy link
Member

I'm happy to do this whichever way is most preferable. @davidkpiano, what do you think?

Let's do the changes and try them out. If your use-case still passes, it's probably fine 👍

@blimmer
Copy link
Contributor Author

blimmer commented Dec 7, 2020

I tested with @Andarist 's patch as well (below), and both work. I'll update now.

diff --git a/node_modules/xstate/es/interpreter.js b/node_modules/xstate/es/interpreter.js
index a35ec06..d2e2abb 100644
--- a/node_modules/xstate/es/interpreter.js
+++ b/node_modules/xstate/es/interpreter.js
@@ -1237,10 +1237,10 @@ function () {
       deferEvents: true,
       clock: {
         setTimeout: function (fn, ms) {
-          return global.setTimeout.call(null, fn, ms);
+          return setTimeout(fn, ms);
         },
         clearTimeout: function (id) {
-          return global.clearTimeout.call(null, id);
+          return clearTimeout(id);
         }
       },
       logger: global.console.log.bind(console),
diff --git a/node_modules/xstate/lib/interpreter.js b/node_modules/xstate/lib/interpreter.js
index 8216933..5f8be29 100644
--- a/node_modules/xstate/lib/interpreter.js
+++ b/node_modules/xstate/lib/interpreter.js
@@ -1039,10 +1039,10 @@ var Interpreter = /** @class */ (function () {
         deferEvents: true,
         clock: {
             setTimeout: function (fn, ms) {
-                return global.setTimeout.call(null, fn, ms);
+                return setTimeout(fn, ms);
             },
             clearTimeout: function (id) {
-                return global.clearTimeout.call(null, id);
+                return clearTimeout(id);
             }
         },
         logger: global.console.log.bind(console),

blimmer and others added 3 commits December 7, 2020 14:30
Co-authored-by: Mateusz Burzyński <mateuszburzynski@gmail.com>
Co-authored-by: Mateusz Burzyński <mateuszburzynski@gmail.com>
Co-authored-by: Mateusz Burzyński <mateuszburzynski@gmail.com>
@blimmer blimmer changed the title Bind clock methods to global thisArg Preserve global context with clock methods (setTimeout/clearTimeout) Dec 7, 2020
@davidkpiano davidkpiano merged commit 180a6e4 into statelyai:master Dec 7, 2020
@github-actions github-actions bot mentioned this pull request Dec 7, 2020
@blimmer blimmer deleted the bug/set-timeout-thisarg branch December 7, 2020 21:48
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 this pull request may close these issues.

Interpretter clock.setTimeout method does not work in Firefox WebExtension content scripts by default
3 participants