@react-three/fiber 9.0.4 → 9.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1136 -1124
- package/dist/declarations/src/core/events.d.ts +92 -92
- package/dist/declarations/src/core/hooks.d.ts +53 -53
- package/dist/declarations/src/core/index.d.ts +13 -13
- package/dist/declarations/src/core/loop.d.ts +31 -31
- package/dist/declarations/src/core/reconciler.d.ts +50 -50
- package/dist/declarations/src/core/renderer.d.ts +89 -89
- package/dist/declarations/src/core/store.d.ts +130 -130
- package/dist/declarations/src/core/utils.d.ts +190 -187
- package/dist/declarations/src/index.d.ts +6 -6
- package/dist/declarations/src/native/Canvas.d.ts +13 -13
- package/dist/declarations/src/native/events.d.ts +4 -4
- package/dist/declarations/src/native.d.ts +6 -6
- package/dist/declarations/src/three-types.d.ts +67 -67
- package/dist/declarations/src/web/Canvas.d.ts +23 -23
- package/dist/declarations/src/web/events.d.ts +4 -4
- package/dist/{events-2895749c.esm.js → events-9ea6854d.esm.js} +114 -95
- package/dist/{events-cee74b95.cjs.dev.js → events-b2f77bcf.cjs.dev.js} +114 -95
- package/dist/{events-ff8de4d2.cjs.prod.js → events-fed10990.cjs.prod.js} +114 -95
- package/dist/react-three-fiber.cjs.dev.js +4 -4
- package/dist/react-three-fiber.cjs.prod.js +4 -4
- package/dist/react-three-fiber.esm.js +5 -5
- package/native/dist/react-three-fiber-native.cjs.dev.js +4 -4
- package/native/dist/react-three-fiber-native.cjs.prod.js +4 -4
- package/native/dist/react-three-fiber-native.esm.js +5 -5
- package/native/package.json +5 -5
- package/package.json +3 -2
- package/readme.md +253 -253
|
@@ -12,30 +12,35 @@ var threeTypes = /*#__PURE__*/Object.freeze({
|
|
|
12
12
|
__proto__: null
|
|
13
13
|
});
|
|
14
14
|
|
|
15
|
-
/**
|
|
16
|
-
* Returns the instance's initial (outmost) root.
|
|
15
|
+
/**
|
|
16
|
+
* Returns the instance's initial (outmost) root.
|
|
17
17
|
*/
|
|
18
18
|
function findInitialRoot(instance) {
|
|
19
19
|
let root = instance.root;
|
|
20
20
|
while (root.getState().previousRoot) root = root.getState().previousRoot;
|
|
21
21
|
return root;
|
|
22
22
|
}
|
|
23
|
-
/**
|
|
24
|
-
* Safely flush async effects when testing, simulating a legacy root.
|
|
23
|
+
/**
|
|
24
|
+
* Safely flush async effects when testing, simulating a legacy root.
|
|
25
25
|
*/
|
|
26
|
-
const act =
|
|
26
|
+
const act = cb => {
|
|
27
|
+
if ('act' in React) {
|
|
28
|
+
return React.act(cb);
|
|
29
|
+
}
|
|
30
|
+
throw new Error('act(...) is not supported in production builds of React');
|
|
31
|
+
};
|
|
27
32
|
const isOrthographicCamera = def => def && def.isOrthographicCamera;
|
|
28
33
|
const isRef = obj => obj && obj.hasOwnProperty('current');
|
|
29
34
|
const isColorRepresentation = value => value != null && (typeof value === 'string' || typeof value === 'number' || value.isColor);
|
|
30
35
|
|
|
31
|
-
/**
|
|
32
|
-
* An SSR-friendly useLayoutEffect.
|
|
33
|
-
*
|
|
34
|
-
* React currently throws a warning when using useLayoutEffect on the server.
|
|
35
|
-
* To get around it, we can conditionally useEffect on the server (no-op) and
|
|
36
|
-
* useLayoutEffect elsewhere.
|
|
37
|
-
*
|
|
38
|
-
* @see https://github.com/facebook/react/issues/14927
|
|
36
|
+
/**
|
|
37
|
+
* An SSR-friendly useLayoutEffect.
|
|
38
|
+
*
|
|
39
|
+
* React currently throws a warning when using useLayoutEffect on the server.
|
|
40
|
+
* To get around it, we can conditionally useEffect on the server (no-op) and
|
|
41
|
+
* useLayoutEffect elsewhere.
|
|
42
|
+
*
|
|
43
|
+
* @see https://github.com/facebook/react/issues/14927
|
|
39
44
|
*/
|
|
40
45
|
const useIsomorphicLayoutEffect = /* @__PURE__ */((_window$document, _window$navigator) => typeof window !== 'undefined' && (((_window$document = window.document) == null ? void 0 : _window$document.createElement) || ((_window$navigator = window.navigator) == null ? void 0 : _window$navigator.product) === 'ReactNative'))() ? React.useLayoutEffect : React.useEffect;
|
|
41
46
|
function useMutableCallback(fn) {
|
|
@@ -43,8 +48,8 @@ function useMutableCallback(fn) {
|
|
|
43
48
|
useIsomorphicLayoutEffect(() => void (ref.current = fn), [fn]);
|
|
44
49
|
return ref;
|
|
45
50
|
}
|
|
46
|
-
/**
|
|
47
|
-
* Bridges renderer Context and StrictMode from a primary renderer.
|
|
51
|
+
/**
|
|
52
|
+
* Bridges renderer Context and StrictMode from a primary renderer.
|
|
48
53
|
*/
|
|
49
54
|
function useBridge() {
|
|
50
55
|
const fiber = useFiber();
|
|
@@ -96,8 +101,8 @@ function calculateDpr(dpr) {
|
|
|
96
101
|
return Array.isArray(dpr) ? Math.min(Math.max(dpr[0], target), dpr[1]) : dpr;
|
|
97
102
|
}
|
|
98
103
|
|
|
99
|
-
/**
|
|
100
|
-
* Returns instance root state
|
|
104
|
+
/**
|
|
105
|
+
* Returns instance root state
|
|
101
106
|
*/
|
|
102
107
|
function getRootState(obj) {
|
|
103
108
|
var _r3f;
|
|
@@ -158,12 +163,14 @@ const is = {
|
|
|
158
163
|
function buildGraph(object) {
|
|
159
164
|
const data = {
|
|
160
165
|
nodes: {},
|
|
161
|
-
materials: {}
|
|
166
|
+
materials: {},
|
|
167
|
+
meshes: {}
|
|
162
168
|
};
|
|
163
169
|
if (object) {
|
|
164
170
|
object.traverse(obj => {
|
|
165
171
|
if (obj.name) data.nodes[obj.name] = obj;
|
|
166
172
|
if (obj.material && !data.materials[obj.material.name]) data.materials[obj.material.name] = obj.material;
|
|
173
|
+
if (obj.isMesh && !data.meshes[obj.name]) data.meshes[obj.name] = obj;
|
|
167
174
|
});
|
|
168
175
|
}
|
|
169
176
|
return data;
|
|
@@ -210,7 +217,6 @@ function prepare(target, root, type, props) {
|
|
|
210
217
|
return instance;
|
|
211
218
|
}
|
|
212
219
|
function resolve(root, key) {
|
|
213
|
-
var _target;
|
|
214
220
|
let target = root[key];
|
|
215
221
|
if (!key.includes('-')) return {
|
|
216
222
|
root,
|
|
@@ -219,12 +225,16 @@ function resolve(root, key) {
|
|
|
219
225
|
};
|
|
220
226
|
|
|
221
227
|
// Resolve pierced target
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
228
|
+
target = root;
|
|
229
|
+
for (const part of key.split('-')) {
|
|
230
|
+
var _target;
|
|
231
|
+
key = part;
|
|
232
|
+
root = target;
|
|
233
|
+
target = (_target = target) == null ? void 0 : _target[key];
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// TODO: change key to 'foo-bar' if target is undefined?
|
|
225
237
|
|
|
226
|
-
// Switch root if atomic
|
|
227
|
-
if (!((_target = target) != null && _target.set)) root = chain.reduce((acc, key) => acc[key], root);
|
|
228
238
|
return {
|
|
229
239
|
root,
|
|
230
240
|
key,
|
|
@@ -455,9 +465,9 @@ function makeId(event) {
|
|
|
455
465
|
return (event.eventObject || event.object).uuid + '/' + event.index + event.instanceId;
|
|
456
466
|
}
|
|
457
467
|
|
|
458
|
-
/**
|
|
459
|
-
* Release pointer captures.
|
|
460
|
-
* This is called by releasePointerCapture in the API, and when an object is removed.
|
|
468
|
+
/**
|
|
469
|
+
* Release pointer captures.
|
|
470
|
+
* This is called by releasePointerCapture in the API, and when an object is removed.
|
|
461
471
|
*/
|
|
462
472
|
function releaseInternalPointerCapture(capturedMap, obj, captures, pointerId) {
|
|
463
473
|
const captureData = captures.get(obj);
|
|
@@ -804,19 +814,19 @@ function createEvents(store) {
|
|
|
804
814
|
if (!(instance != null && instance.eventCount)) return;
|
|
805
815
|
const handlers = instance.handlers;
|
|
806
816
|
|
|
807
|
-
/*
|
|
808
|
-
MAYBE TODO, DELETE IF NOT:
|
|
809
|
-
Check if the object is captured, captured events should not have intersects running in parallel
|
|
810
|
-
But wouldn't it be better to just replace capturedMap with a single entry?
|
|
811
|
-
Also, are we OK with straight up making picking up multiple objects impossible?
|
|
812
|
-
|
|
813
|
-
const pointerId = (data as ThreeEvent<PointerEvent>).pointerId
|
|
814
|
-
if (pointerId !== undefined) {
|
|
815
|
-
const capturedMeshSet = internal.capturedMap.get(pointerId)
|
|
816
|
-
if (capturedMeshSet) {
|
|
817
|
-
const captured = capturedMeshSet.get(eventObject)
|
|
818
|
-
if (captured && captured.localState.stopped) return
|
|
819
|
-
}
|
|
817
|
+
/*
|
|
818
|
+
MAYBE TODO, DELETE IF NOT:
|
|
819
|
+
Check if the object is captured, captured events should not have intersects running in parallel
|
|
820
|
+
But wouldn't it be better to just replace capturedMap with a single entry?
|
|
821
|
+
Also, are we OK with straight up making picking up multiple objects impossible?
|
|
822
|
+
|
|
823
|
+
const pointerId = (data as ThreeEvent<PointerEvent>).pointerId
|
|
824
|
+
if (pointerId !== undefined) {
|
|
825
|
+
const capturedMeshSet = internal.capturedMap.get(pointerId)
|
|
826
|
+
if (capturedMeshSet) {
|
|
827
|
+
const captured = capturedMeshSet.get(eventObject)
|
|
828
|
+
if (captured && captured.localState.stopped) return
|
|
829
|
+
}
|
|
820
830
|
}*/
|
|
821
831
|
|
|
822
832
|
if (isPointerMove) {
|
|
@@ -1107,11 +1117,11 @@ const createStore = (invalidate, advance) => {
|
|
|
1107
1117
|
return rootStore;
|
|
1108
1118
|
};
|
|
1109
1119
|
|
|
1110
|
-
/**
|
|
1111
|
-
* Exposes an object's {@link Instance}.
|
|
1112
|
-
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#useInstanceHandle
|
|
1113
|
-
*
|
|
1114
|
-
* **Note**: this is an escape hatch to react-internal fields. Expect this to change significantly between versions.
|
|
1120
|
+
/**
|
|
1121
|
+
* Exposes an object's {@link Instance}.
|
|
1122
|
+
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#useInstanceHandle
|
|
1123
|
+
*
|
|
1124
|
+
* **Note**: this is an escape hatch to react-internal fields. Expect this to change significantly between versions.
|
|
1115
1125
|
*/
|
|
1116
1126
|
function useInstanceHandle(ref) {
|
|
1117
1127
|
const instance = React.useRef(null);
|
|
@@ -1119,9 +1129,9 @@ function useInstanceHandle(ref) {
|
|
|
1119
1129
|
return instance;
|
|
1120
1130
|
}
|
|
1121
1131
|
|
|
1122
|
-
/**
|
|
1123
|
-
* Returns the R3F Canvas' Zustand store. Useful for [transient updates](https://github.com/pmndrs/zustand#transient-updates-for-often-occurring-state-changes).
|
|
1124
|
-
* @see https://docs.pmnd.rs/react-three-fiber/api/hooks#usestore
|
|
1132
|
+
/**
|
|
1133
|
+
* Returns the R3F Canvas' Zustand store. Useful for [transient updates](https://github.com/pmndrs/zustand#transient-updates-for-often-occurring-state-changes).
|
|
1134
|
+
* @see https://docs.pmnd.rs/react-three-fiber/api/hooks#usestore
|
|
1125
1135
|
*/
|
|
1126
1136
|
function useStore() {
|
|
1127
1137
|
const store = React.useContext(context);
|
|
@@ -1129,18 +1139,18 @@ function useStore() {
|
|
|
1129
1139
|
return store;
|
|
1130
1140
|
}
|
|
1131
1141
|
|
|
1132
|
-
/**
|
|
1133
|
-
* Accesses R3F's internal state, containing renderer, canvas, scene, etc.
|
|
1134
|
-
* @see https://docs.pmnd.rs/react-three-fiber/api/hooks#usethree
|
|
1142
|
+
/**
|
|
1143
|
+
* Accesses R3F's internal state, containing renderer, canvas, scene, etc.
|
|
1144
|
+
* @see https://docs.pmnd.rs/react-three-fiber/api/hooks#usethree
|
|
1135
1145
|
*/
|
|
1136
1146
|
function useThree(selector = state => state, equalityFn) {
|
|
1137
1147
|
return useStore()(selector, equalityFn);
|
|
1138
1148
|
}
|
|
1139
1149
|
|
|
1140
|
-
/**
|
|
1141
|
-
* Executes a callback before render in a shared frame loop.
|
|
1142
|
-
* Can order effects with render priority or manually render with a positive priority.
|
|
1143
|
-
* @see https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe
|
|
1150
|
+
/**
|
|
1151
|
+
* Executes a callback before render in a shared frame loop.
|
|
1152
|
+
* Can order effects with render priority or manually render with a positive priority.
|
|
1153
|
+
* @see https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe
|
|
1144
1154
|
*/
|
|
1145
1155
|
function useFrame(callback, renderPriority = 0) {
|
|
1146
1156
|
const store = useStore();
|
|
@@ -1152,9 +1162,9 @@ function useFrame(callback, renderPriority = 0) {
|
|
|
1152
1162
|
return null;
|
|
1153
1163
|
}
|
|
1154
1164
|
|
|
1155
|
-
/**
|
|
1156
|
-
* Returns a node graph of an object with named nodes & materials.
|
|
1157
|
-
* @see https://docs.pmnd.rs/react-three-fiber/api/hooks#usegraph
|
|
1165
|
+
/**
|
|
1166
|
+
* Returns a node graph of an object with named nodes & materials.
|
|
1167
|
+
* @see https://docs.pmnd.rs/react-three-fiber/api/hooks#usegraph
|
|
1158
1168
|
*/
|
|
1159
1169
|
function useGraph(object) {
|
|
1160
1170
|
return React.useMemo(() => buildGraph(object), [object]);
|
|
@@ -1190,11 +1200,11 @@ function loadingFn(extensions, onProgress) {
|
|
|
1190
1200
|
};
|
|
1191
1201
|
}
|
|
1192
1202
|
|
|
1193
|
-
/**
|
|
1194
|
-
* Synchronously loads and caches assets with a three loader.
|
|
1195
|
-
*
|
|
1196
|
-
* Note: this hook's caller must be wrapped with `React.Suspense`
|
|
1197
|
-
* @see https://docs.pmnd.rs/react-three-fiber/api/hooks#useloader
|
|
1203
|
+
/**
|
|
1204
|
+
* Synchronously loads and caches assets with a three loader.
|
|
1205
|
+
*
|
|
1206
|
+
* Note: this hook's caller must be wrapped with `React.Suspense`
|
|
1207
|
+
* @see https://docs.pmnd.rs/react-three-fiber/api/hooks#useloader
|
|
1198
1208
|
*/
|
|
1199
1209
|
function useLoader(loader, input, extensions, onProgress) {
|
|
1200
1210
|
// Use suspense to load async assets
|
|
@@ -1206,16 +1216,16 @@ function useLoader(loader, input, extensions, onProgress) {
|
|
|
1206
1216
|
return Array.isArray(input) ? results : results[0];
|
|
1207
1217
|
}
|
|
1208
1218
|
|
|
1209
|
-
/**
|
|
1210
|
-
* Preloads an asset into cache as a side-effect.
|
|
1219
|
+
/**
|
|
1220
|
+
* Preloads an asset into cache as a side-effect.
|
|
1211
1221
|
*/
|
|
1212
1222
|
useLoader.preload = function (loader, input, extensions) {
|
|
1213
1223
|
const keys = Array.isArray(input) ? input : [input];
|
|
1214
1224
|
return preload(loadingFn(extensions), [loader, ...keys]);
|
|
1215
1225
|
};
|
|
1216
1226
|
|
|
1217
|
-
/**
|
|
1218
|
-
* Removes a loaded asset from cache.
|
|
1227
|
+
/**
|
|
1228
|
+
* Removes a loaded asset from cache.
|
|
1219
1229
|
*/
|
|
1220
1230
|
useLoader.clear = function (loader, input) {
|
|
1221
1231
|
const keys = Array.isArray(input) ? input : [input];
|
|
@@ -1331,15 +1341,24 @@ function handleContainerEffects(parent, child, beforeChild) {
|
|
|
1331
1341
|
} else if (isObject3D(child.object) && isObject3D(parent.object)) {
|
|
1332
1342
|
const childIndex = parent.object.children.indexOf(beforeChild == null ? void 0 : beforeChild.object);
|
|
1333
1343
|
if (beforeChild && childIndex !== -1) {
|
|
1334
|
-
child
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1344
|
+
// If the child is already in the parent's children array, move it to the new position
|
|
1345
|
+
// Otherwise, just insert it at the target position
|
|
1346
|
+
const existingIndex = parent.object.children.indexOf(child.object);
|
|
1347
|
+
if (existingIndex !== -1) {
|
|
1348
|
+
parent.object.children.splice(existingIndex, 1);
|
|
1349
|
+
const adjustedIndex = existingIndex < childIndex ? childIndex - 1 : childIndex;
|
|
1350
|
+
parent.object.children.splice(adjustedIndex, 0, child.object);
|
|
1351
|
+
} else {
|
|
1352
|
+
child.object.parent = parent.object;
|
|
1353
|
+
parent.object.children.splice(childIndex, 0, child.object);
|
|
1354
|
+
child.object.dispatchEvent({
|
|
1355
|
+
type: 'added'
|
|
1356
|
+
});
|
|
1357
|
+
parent.object.dispatchEvent({
|
|
1358
|
+
type: 'childadded',
|
|
1359
|
+
child: child.object
|
|
1360
|
+
});
|
|
1361
|
+
}
|
|
1343
1362
|
} else {
|
|
1344
1363
|
parent.object.add(child.object);
|
|
1345
1364
|
}
|
|
@@ -2040,10 +2059,10 @@ function Portal({
|
|
|
2040
2059
|
children,
|
|
2041
2060
|
container
|
|
2042
2061
|
}) {
|
|
2043
|
-
/** This has to be a component because it would not be able to call useThree/useStore otherwise since
|
|
2044
|
-
* if this is our environment, then we are not in r3f's renderer but in react-dom, it would trigger
|
|
2045
|
-
* the "R3F hooks can only be used within the Canvas component!" warning:
|
|
2046
|
-
* <Canvas>
|
|
2062
|
+
/** This has to be a component because it would not be able to call useThree/useStore otherwise since
|
|
2063
|
+
* if this is our environment, then we are not in r3f's renderer but in react-dom, it would trigger
|
|
2064
|
+
* the "R3F hooks can only be used within the Canvas component!" warning:
|
|
2065
|
+
* <Canvas>
|
|
2047
2066
|
* {createPortal(...)} */
|
|
2048
2067
|
const {
|
|
2049
2068
|
events,
|
|
@@ -2135,21 +2154,21 @@ const globalEffects = new Set();
|
|
|
2135
2154
|
const globalAfterEffects = new Set();
|
|
2136
2155
|
const globalTailEffects = new Set();
|
|
2137
2156
|
|
|
2138
|
-
/**
|
|
2139
|
-
* Adds a global render callback which is called each frame.
|
|
2140
|
-
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addEffect
|
|
2157
|
+
/**
|
|
2158
|
+
* Adds a global render callback which is called each frame.
|
|
2159
|
+
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addEffect
|
|
2141
2160
|
*/
|
|
2142
2161
|
const addEffect = callback => createSubs(callback, globalEffects);
|
|
2143
2162
|
|
|
2144
|
-
/**
|
|
2145
|
-
* Adds a global after-render callback which is called each frame.
|
|
2146
|
-
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addAfterEffect
|
|
2163
|
+
/**
|
|
2164
|
+
* Adds a global after-render callback which is called each frame.
|
|
2165
|
+
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addAfterEffect
|
|
2147
2166
|
*/
|
|
2148
2167
|
const addAfterEffect = callback => createSubs(callback, globalAfterEffects);
|
|
2149
2168
|
|
|
2150
|
-
/**
|
|
2151
|
-
* Adds a global callback which is called when rendering stops.
|
|
2152
|
-
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addTail
|
|
2169
|
+
/**
|
|
2170
|
+
* Adds a global callback which is called when rendering stops.
|
|
2171
|
+
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addTail
|
|
2153
2172
|
*/
|
|
2154
2173
|
const addTail = callback => createSubs(callback, globalTailEffects);
|
|
2155
2174
|
function run(effects, timestamp) {
|
|
@@ -2237,9 +2256,9 @@ function loop(timestamp) {
|
|
|
2237
2256
|
}
|
|
2238
2257
|
}
|
|
2239
2258
|
|
|
2240
|
-
/**
|
|
2241
|
-
* Invalidates the view, requesting a frame to be rendered. Will globally invalidate unless passed a root's state.
|
|
2242
|
-
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#invalidate
|
|
2259
|
+
/**
|
|
2260
|
+
* Invalidates the view, requesting a frame to be rendered. Will globally invalidate unless passed a root's state.
|
|
2261
|
+
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#invalidate
|
|
2243
2262
|
*/
|
|
2244
2263
|
function invalidate(state, frames = 1) {
|
|
2245
2264
|
var _state$gl$xr2;
|
|
@@ -2266,9 +2285,9 @@ function invalidate(state, frames = 1) {
|
|
|
2266
2285
|
}
|
|
2267
2286
|
}
|
|
2268
2287
|
|
|
2269
|
-
/**
|
|
2270
|
-
* Advances the frameloop and runs render effects, useful for when manually rendering via `frameloop="never"`.
|
|
2271
|
-
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#advance
|
|
2288
|
+
/**
|
|
2289
|
+
* Advances the frameloop and runs render effects, useful for when manually rendering via `frameloop="never"`.
|
|
2290
|
+
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#advance
|
|
2272
2291
|
*/
|
|
2273
2292
|
function advance(timestamp, runGlobalEffects = true, state, frame) {
|
|
2274
2293
|
if (runGlobalEffects) flushGlobalEffects('before', timestamp);
|