Skip to content

Commit 504fb24

Browse files
authored
Fix no clearImmediate and no store prop (#4709)
* Fix no clearImmediate and store prop * Update PR number * Clean up * Fix test
1 parent 753b8a6 commit 504fb24

File tree

8 files changed

+141
-53
lines changed

8 files changed

+141
-53
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
5050
- Fixes [#4652](https://github.com/microsoft/BotFramework-WebChat/issues/4652). Keyboard help screen, activity focus traps, and chat history terminator should not be hidden behind `aria-hidden` because they are focusable, by [@compulim](https://github.com/compulim), in PR [#4659](https://github.com/microsoft/BotFramework-WebChat/pull/4659)
5151
- Fixes [#4665](https://github.com/microsoft/BotFramework-WebChat/issues/4665). Updated development server with latest ESBuild API, by [@compulim](https://github.com/compulim), in PR [#4662](https://github.com/microsoft/BotFramework-WebChat/pull/4662).
5252
- Fixes [#4706](https://github.com/microsoft/BotFramework-WebChat/issues/4706). Send button and <kbd>ENTER</kbd> key should function after reconnected, by [@compulim](https://github.com/compulim), in PR [#4707](https://github.com/microsoft/BotFramework-WebChat/pull/4707).
53+
- Fixes [#4708](https://github.com/microsoft/BotFramework-WebChat/issues/4708). Should function properly in browsers without `setImmediate` or without passing `store` prop, by [@compulim](https://github.com/compulim), in PR [#4709](https://github.com/microsoft/BotFramework-WebChat/pull/4709).
5354

5455
### Changed
5556

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<!DOCTYPE html>
2+
<html lang="en-US">
3+
<head>
4+
<link href="/assets/index.css" rel="stylesheet" type="text/css" />
5+
<script crossorigin="anonymous" src="/test-harness.js"></script>
6+
<script crossorigin="anonymous" src="/test-page-object.js"></script>
7+
<script crossorigin="anonymous" src="/__dist__/webchat-es5.js"></script>
8+
</head>
9+
<body>
10+
<main id="webchat"></main>
11+
<script>
12+
run(async function () {
13+
WebChat.renderWebChat(
14+
{
15+
directLine: WebChat.createDirectLine({ token: await testHelpers.token.fetchDirectLineToken() })
16+
},
17+
document.getElementById('webchat')
18+
);
19+
20+
// WHEN: Connectivity status should show during connection.
21+
await pageConditions.became('connectivity status should show', () => pageElements.connectivityStatus(), 1000);
22+
23+
// THEN: Connectivity status should hide after connected.
24+
await pageConditions.became('connectivity status should hide after connected', () => !pageElements.connectivityStatus(), 1000);
25+
26+
await host.snapshot();
27+
});
28+
</script>
29+
</body>
30+
</html>
+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/** @jest-environment ./packages/test/harness/src/host/jest/WebDriverEnvironment.js */
2+
3+
describe('simple without createStore', () => {
4+
test('should render UI.', () => runHTML('simple.noCreateStore.html'));
5+
});

packages/api/src/hooks/Composer.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -748,7 +748,7 @@ const ComposerWithStore = ({ onTelemetry, store, ...props }: ComposerWithStorePr
748748
const memoizedStore = useMemo(() => {
749749
const nextStore = store || createStoreWithOptions({ ponyfill });
750750

751-
const storePonyfill = store.getState().internal?.ponyfill || {};
751+
const storePonyfill = nextStore.getState().internal?.ponyfill || {};
752752

753753
const keys = new Set([...Object.keys(storePonyfill), ...Object.keys(ponyfill)]);
754754

packages/api/src/providers/Ponyfill/PonyfillComposer.tsx

+52-25
Original file line numberDiff line numberDiff line change
@@ -24,31 +24,58 @@ const PonyfillComposer = ({ children, ponyfill: partialPonyfill }: Props) => {
2424

2525
// TODO: [P2] Dedupe: when we have an utility package, move this code there and mark it as internal use.
2626
const ponyfill = useMemo<GlobalScopePonyfill>(
27-
() => ({
28-
// Using clock functions from global if not provided.
29-
// eslint-disable-next-line no-restricted-globals
30-
cancelAnimationFrame: partialPonyfill?.cancelAnimationFrame || cancelAnimationFrame.bind(globalThis),
31-
// eslint-disable-next-line no-restricted-globals
32-
cancelIdleCallback: partialPonyfill?.cancelIdleCallback || cancelIdleCallback.bind(globalThis),
33-
// eslint-disable-next-line no-restricted-globals
34-
clearImmediate: partialPonyfill?.clearImmediate || clearImmediate.bind(globalThis),
35-
// eslint-disable-next-line no-restricted-globals
36-
clearInterval: partialPonyfill?.clearInterval || clearInterval.bind(globalThis),
37-
// eslint-disable-next-line no-restricted-globals
38-
clearTimeout: partialPonyfill?.clearTimeout || clearTimeout.bind(globalThis),
39-
// eslint-disable-next-line no-restricted-globals
40-
Date: partialPonyfill?.Date || Date,
41-
// eslint-disable-next-line no-restricted-globals
42-
requestAnimationFrame: partialPonyfill?.requestAnimationFrame || requestAnimationFrame.bind(globalThis),
43-
// eslint-disable-next-line no-restricted-globals
44-
requestIdleCallback: partialPonyfill?.requestIdleCallback || requestIdleCallback.bind(globalThis),
45-
// eslint-disable-next-line no-restricted-globals
46-
setImmediate: partialPonyfill?.setImmediate || setImmediate.bind(globalThis),
47-
// eslint-disable-next-line no-restricted-globals
48-
setInterval: partialPonyfill?.setInterval || setInterval.bind(globalThis),
49-
// eslint-disable-next-line no-restricted-globals
50-
setTimeout: partialPonyfill?.setTimeout || setTimeout.bind(globalThis)
51-
}),
27+
// The complexity is introduced by the check of ponyfill.
28+
// eslint-disable-next-line complexity
29+
() => {
30+
// IE Mode does not have `globalThis`.
31+
const globalThisOrWindow = typeof globalThis === 'undefined' ? window : globalThis;
32+
33+
return {
34+
cancelAnimationFrame:
35+
partialPonyfill?.cancelAnimationFrame ||
36+
// Using clock functions from global if not provided.
37+
// eslint-disable-next-line no-restricted-globals
38+
(typeof cancelAnimationFrame === 'function' ? cancelAnimationFrame.bind(globalThisOrWindow) : undefined),
39+
cancelIdleCallback:
40+
partialPonyfill?.cancelIdleCallback ||
41+
// eslint-disable-next-line no-restricted-globals
42+
(typeof cancelIdleCallback === 'function' ? cancelIdleCallback.bind(globalThisOrWindow) : undefined),
43+
clearImmediate:
44+
partialPonyfill?.clearImmediate ||
45+
// eslint-disable-next-line no-restricted-globals
46+
(typeof clearImmediate === 'function' ? clearImmediate.bind(globalThisOrWindow) : undefined),
47+
clearInterval:
48+
partialPonyfill?.clearInterval ||
49+
// eslint-disable-next-line no-restricted-globals
50+
(typeof clearInterval === 'function' ? clearInterval.bind(globalThisOrWindow) : undefined),
51+
clearTimeout:
52+
partialPonyfill?.clearTimeout ||
53+
// eslint-disable-next-line no-restricted-globals
54+
(typeof clearTimeout === 'function' ? clearTimeout.bind(globalThisOrWindow) : undefined),
55+
// eslint-disable-next-line no-restricted-globals
56+
Date: partialPonyfill?.Date || Date,
57+
requestAnimationFrame:
58+
partialPonyfill?.requestAnimationFrame ||
59+
// eslint-disable-next-line no-restricted-globals
60+
(typeof requestAnimationFrame === 'function' ? requestAnimationFrame.bind(globalThisOrWindow) : undefined),
61+
requestIdleCallback:
62+
partialPonyfill?.requestIdleCallback ||
63+
// eslint-disable-next-line no-restricted-globals
64+
(typeof requestIdleCallback === 'function' ? requestIdleCallback.bind(globalThisOrWindow) : undefined),
65+
setImmediate:
66+
partialPonyfill?.setImmediate ||
67+
// eslint-disable-next-line no-restricted-globals
68+
(typeof setImmediate === 'function' ? setImmediate.bind(globalThisOrWindow) : undefined),
69+
setInterval:
70+
partialPonyfill?.setInterval ||
71+
// eslint-disable-next-line no-restricted-globals
72+
(typeof setInterval === 'function' ? setInterval.bind(globalThisOrWindow) : undefined),
73+
setTimeout:
74+
partialPonyfill?.setTimeout ||
75+
// eslint-disable-next-line no-restricted-globals
76+
(typeof setTimeout === 'function' ? setTimeout.bind(globalThisOrWindow) : undefined)
77+
};
78+
},
5279
[partialPonyfill]
5380
);
5481

packages/core/src/createStore.ts

+46-21
Original file line numberDiff line numberDiff line change
@@ -53,34 +53,59 @@ function createEnhancerAndSagaMiddleware(getStore, ...middlewares) {
5353
*
5454
* This store is critical for Web Chat business logics to operate, please use with cautions.
5555
*/
56+
57+
// The complexity is introduced by the check of ponyfill.
58+
// eslint-disable-next-line complexity
5659
export function withOptions(options: CreateStoreOptions, initialState?, ...middlewares): Store {
60+
// IE Mode does not have `globalThis`.
61+
const globalThisOrWindow = typeof globalThis === 'undefined' ? window : globalThis;
5762
const ponyfillFromOptions: Partial<GlobalScopePonyfill> = options.ponyfill || {};
5863

5964
// TODO: [P2] Dedupe: when we have an utility package, move this code there and mark it as internal use.
6065
const ponyfill: GlobalScopePonyfill = {
61-
// Using clock functions from global if not provided.
62-
// eslint-disable-next-line no-restricted-globals
63-
cancelAnimationFrame: ponyfillFromOptions.cancelAnimationFrame || cancelAnimationFrame.bind(globalThis),
64-
// eslint-disable-next-line no-restricted-globals
65-
cancelIdleCallback: ponyfillFromOptions.cancelIdleCallback || cancelIdleCallback.bind(globalThis),
66-
// eslint-disable-next-line no-restricted-globals
67-
clearImmediate: ponyfillFromOptions.clearImmediate || clearImmediate.bind(globalThis),
68-
// eslint-disable-next-line no-restricted-globals
69-
clearInterval: ponyfillFromOptions.clearInterval || clearInterval.bind(globalThis),
70-
// eslint-disable-next-line no-restricted-globals
71-
clearTimeout: ponyfillFromOptions.clearTimeout || clearTimeout.bind(globalThis),
66+
cancelAnimationFrame:
67+
ponyfillFromOptions.cancelAnimationFrame ||
68+
// Using clock functions from global if not provided.
69+
// eslint-disable-next-line no-restricted-globals
70+
(typeof cancelAnimationFrame === 'function' ? cancelAnimationFrame.bind(globalThisOrWindow) : undefined),
71+
cancelIdleCallback:
72+
ponyfillFromOptions.cancelIdleCallback ||
73+
// eslint-disable-next-line no-restricted-globals
74+
(typeof cancelIdleCallback === 'function' ? cancelIdleCallback.bind(globalThisOrWindow) : undefined),
75+
clearImmediate:
76+
ponyfillFromOptions.clearImmediate ||
77+
// eslint-disable-next-line no-restricted-globals
78+
(typeof clearImmediate === 'function' ? clearImmediate.bind(globalThisOrWindow) : undefined),
79+
clearInterval:
80+
ponyfillFromOptions.clearInterval ||
81+
// eslint-disable-next-line no-restricted-globals
82+
(typeof clearInterval === 'function' ? clearInterval.bind(globalThisOrWindow) : undefined),
83+
clearTimeout:
84+
ponyfillFromOptions.clearTimeout ||
85+
// eslint-disable-next-line no-restricted-globals
86+
(typeof clearTimeout === 'function' ? clearTimeout.bind(globalThisOrWindow) : undefined),
7287
// eslint-disable-next-line no-restricted-globals
7388
Date: ponyfillFromOptions.Date || Date,
74-
// eslint-disable-next-line no-restricted-globals
75-
requestAnimationFrame: ponyfillFromOptions.requestAnimationFrame || requestAnimationFrame.bind(globalThis),
76-
// eslint-disable-next-line no-restricted-globals
77-
requestIdleCallback: ponyfillFromOptions.requestIdleCallback || requestIdleCallback.bind(globalThis),
78-
// eslint-disable-next-line no-restricted-globals
79-
setImmediate: ponyfillFromOptions.setImmediate || setImmediate.bind(globalThis),
80-
// eslint-disable-next-line no-restricted-globals
81-
setInterval: ponyfillFromOptions.setInterval || setInterval.bind(globalThis),
82-
// eslint-disable-next-line no-restricted-globals
83-
setTimeout: ponyfillFromOptions.setTimeout || setTimeout.bind(globalThis)
89+
requestAnimationFrame:
90+
ponyfillFromOptions.requestAnimationFrame ||
91+
// eslint-disable-next-line no-restricted-globals
92+
(typeof requestAnimationFrame === 'function' ? requestAnimationFrame.bind(globalThisOrWindow) : undefined),
93+
requestIdleCallback:
94+
ponyfillFromOptions.requestIdleCallback ||
95+
// eslint-disable-next-line no-restricted-globals
96+
(typeof requestIdleCallback === 'function' ? requestIdleCallback.bind(globalThisOrWindow) : undefined),
97+
setImmediate:
98+
ponyfillFromOptions.setImmediate ||
99+
// eslint-disable-next-line no-restricted-globals
100+
(typeof setImmediate === 'function' ? setImmediate.bind(globalThisOrWindow) : undefined),
101+
setInterval:
102+
ponyfillFromOptions.setInterval ||
103+
// eslint-disable-next-line no-restricted-globals
104+
(typeof setInterval === 'function' ? setInterval.bind(globalThisOrWindow) : undefined),
105+
setTimeout:
106+
ponyfillFromOptions.setTimeout ||
107+
// eslint-disable-next-line no-restricted-globals
108+
(typeof setTimeout === 'function' ? setTimeout.bind(globalThisOrWindow) : undefined)
84109
};
85110

86111
// We are sure the "getStore" (first argument) is not called on "createEnhancerAndSagaMiddleware()".

packages/core/src/types/internal/GlobalScopeClock.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
export type GlobalScopeClock = {
22
// eslint-disable-next-line no-restricted-globals
3-
cancelAnimationFrame: typeof cancelAnimationFrame;
3+
cancelAnimationFrame?: typeof cancelAnimationFrame;
44
// eslint-disable-next-line no-restricted-globals
5-
cancelIdleCallback: typeof cancelIdleCallback;
5+
cancelIdleCallback?: typeof cancelIdleCallback;
66
// eslint-disable-next-line no-restricted-globals
7-
clearImmediate: typeof clearImmediate;
7+
clearImmediate?: typeof clearImmediate;
88
// eslint-disable-next-line no-restricted-globals
99
clearInterval: typeof clearInterval;
1010
// eslint-disable-next-line no-restricted-globals
1111
clearTimeout: typeof clearTimeout;
1212
// eslint-disable-next-line no-restricted-globals
1313
Date: typeof Date;
1414
// eslint-disable-next-line no-restricted-globals
15-
requestAnimationFrame: typeof requestAnimationFrame;
15+
requestAnimationFrame?: typeof requestAnimationFrame;
1616
// eslint-disable-next-line no-restricted-globals
17-
requestIdleCallback: typeof requestIdleCallback;
17+
requestIdleCallback?: typeof requestIdleCallback;
1818
// eslint-disable-next-line no-restricted-globals
19-
setImmediate: typeof setImmediate;
19+
setImmediate?: typeof setImmediate;
2020
// eslint-disable-next-line no-restricted-globals
2121
setInterval: typeof setInterval;
2222
// eslint-disable-next-line no-restricted-globals

0 commit comments

Comments
 (0)