Skip to content

Commit a2531fa

Browse files
committed
Remove client caching from cache() API (#27977)
We haven't yet decided how we want `cache` to work on the client. The lifetime of the cache is more complex than on the server, where it only has to live as long as a single request. Since it's more important to ship this on the server, we're removing the existing behavior from the client for now. On the client (i.e. not a Server Components environment) `cache` will have not have any caching behavior. `cache(fn)` will return the function as-is. We intend to implement client caching in a future major release. In the meantime, it's only exposed as an API so that Shared Components can use per-request caching on the server without breaking on the client. DiffTrain build for [5c60736](5c60736)
1 parent 0cd227f commit a2531fa

9 files changed

+43
-383
lines changed

compiled/facebook-www/REVISION

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
f16344ea6db5bcc108de80dbc39a41ec28e8210d
1+
5c607369ceebe56d85175df84b7b6ad58dd25e1f

compiled/facebook-www/React-dev.classic.js

+15-103
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ if (__DEV__) {
2424
) {
2525
__REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error());
2626
}
27-
var ReactVersion = "18.3.0-www-classic-28af9135";
27+
var ReactVersion = "18.3.0-www-classic-dd3d212c";
2828

2929
// ATTENTION
3030
// When adding new symbols to this file,
@@ -2777,110 +2777,22 @@ if (__DEV__) {
27772777
return elementType;
27782778
}
27792779

2780-
var UNTERMINATED = 0;
2781-
var TERMINATED = 1;
2782-
var ERRORED = 2;
2783-
2784-
function createCacheRoot() {
2785-
return new WeakMap();
2786-
}
2787-
2788-
function createCacheNode() {
2789-
return {
2790-
s: UNTERMINATED,
2791-
// status, represents whether the cached computation returned a value or threw an error
2792-
v: undefined,
2793-
// value, either the cached result or an error, depending on s
2794-
o: null,
2795-
// object cache, a WeakMap where non-primitive arguments are stored
2796-
p: null // primitive cache, a regular Map where primitive arguments are stored.
2797-
};
2798-
}
2799-
28002780
function cache(fn) {
2781+
// On the client (i.e. not a Server Components environment) `cache` has
2782+
// no caching behavior. We just return the function as-is.
2783+
//
2784+
// We intend to implement client caching in a future major release. In the
2785+
// meantime, it's only exposed as an API so that Shared Components can use
2786+
// per-request caching on the server without breaking on the client. But it
2787+
// does mean they need to be aware of the behavioral difference.
2788+
//
2789+
// The rest of the behavior is the same as the server implementation — it
2790+
// returns a new reference, extra properties like `displayName` are not
2791+
// preserved, the length of the new function is 0, etc. That way apps can't
2792+
// accidentally depend on those details.
28012793
return function () {
2802-
var dispatcher = ReactCurrentCache.current;
2803-
2804-
if (!dispatcher) {
2805-
// If there is no dispatcher, then we treat this as not being cached.
2806-
// $FlowFixMe[incompatible-call]: We don't want to use rest arguments since we transpile the code.
2807-
return fn.apply(null, arguments);
2808-
}
2809-
2810-
var fnMap = dispatcher.getCacheForType(createCacheRoot);
2811-
var fnNode = fnMap.get(fn);
2812-
var cacheNode;
2813-
2814-
if (fnNode === undefined) {
2815-
cacheNode = createCacheNode();
2816-
fnMap.set(fn, cacheNode);
2817-
} else {
2818-
cacheNode = fnNode;
2819-
}
2820-
2821-
for (var i = 0, l = arguments.length; i < l; i++) {
2822-
var arg = arguments[i];
2823-
2824-
if (
2825-
typeof arg === "function" ||
2826-
(typeof arg === "object" && arg !== null)
2827-
) {
2828-
// Objects go into a WeakMap
2829-
var objectCache = cacheNode.o;
2830-
2831-
if (objectCache === null) {
2832-
cacheNode.o = objectCache = new WeakMap();
2833-
}
2834-
2835-
var objectNode = objectCache.get(arg);
2836-
2837-
if (objectNode === undefined) {
2838-
cacheNode = createCacheNode();
2839-
objectCache.set(arg, cacheNode);
2840-
} else {
2841-
cacheNode = objectNode;
2842-
}
2843-
} else {
2844-
// Primitives go into a regular Map
2845-
var primitiveCache = cacheNode.p;
2846-
2847-
if (primitiveCache === null) {
2848-
cacheNode.p = primitiveCache = new Map();
2849-
}
2850-
2851-
var primitiveNode = primitiveCache.get(arg);
2852-
2853-
if (primitiveNode === undefined) {
2854-
cacheNode = createCacheNode();
2855-
primitiveCache.set(arg, cacheNode);
2856-
} else {
2857-
cacheNode = primitiveNode;
2858-
}
2859-
}
2860-
}
2861-
2862-
if (cacheNode.s === TERMINATED) {
2863-
return cacheNode.v;
2864-
}
2865-
2866-
if (cacheNode.s === ERRORED) {
2867-
throw cacheNode.v;
2868-
}
2869-
2870-
try {
2871-
// $FlowFixMe[incompatible-call]: We don't want to use rest arguments since we transpile the code.
2872-
var result = fn.apply(null, arguments);
2873-
var terminatedNode = cacheNode;
2874-
terminatedNode.s = TERMINATED;
2875-
terminatedNode.v = result;
2876-
return result;
2877-
} catch (error) {
2878-
// We store the first error that's thrown and rethrow it.
2879-
var erroredNode = cacheNode;
2880-
erroredNode.s = ERRORED;
2881-
erroredNode.v = error;
2882-
throw error;
2883-
}
2794+
// $FlowFixMe[incompatible-call]: We don't want to use rest arguments since we transpile the code.
2795+
return fn.apply(null, arguments);
28842796
};
28852797
}
28862798

compiled/facebook-www/React-dev.modern.js

+15-103
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ if (__DEV__) {
2424
) {
2525
__REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error());
2626
}
27-
var ReactVersion = "18.3.0-www-modern-b277b01a";
27+
var ReactVersion = "18.3.0-www-modern-50d838b5";
2828

2929
// ATTENTION
3030
// When adding new symbols to this file,
@@ -2742,110 +2742,22 @@ if (__DEV__) {
27422742
return elementType;
27432743
}
27442744

2745-
var UNTERMINATED = 0;
2746-
var TERMINATED = 1;
2747-
var ERRORED = 2;
2748-
2749-
function createCacheRoot() {
2750-
return new WeakMap();
2751-
}
2752-
2753-
function createCacheNode() {
2754-
return {
2755-
s: UNTERMINATED,
2756-
// status, represents whether the cached computation returned a value or threw an error
2757-
v: undefined,
2758-
// value, either the cached result or an error, depending on s
2759-
o: null,
2760-
// object cache, a WeakMap where non-primitive arguments are stored
2761-
p: null // primitive cache, a regular Map where primitive arguments are stored.
2762-
};
2763-
}
2764-
27652745
function cache(fn) {
2746+
// On the client (i.e. not a Server Components environment) `cache` has
2747+
// no caching behavior. We just return the function as-is.
2748+
//
2749+
// We intend to implement client caching in a future major release. In the
2750+
// meantime, it's only exposed as an API so that Shared Components can use
2751+
// per-request caching on the server without breaking on the client. But it
2752+
// does mean they need to be aware of the behavioral difference.
2753+
//
2754+
// The rest of the behavior is the same as the server implementation — it
2755+
// returns a new reference, extra properties like `displayName` are not
2756+
// preserved, the length of the new function is 0, etc. That way apps can't
2757+
// accidentally depend on those details.
27662758
return function () {
2767-
var dispatcher = ReactCurrentCache.current;
2768-
2769-
if (!dispatcher) {
2770-
// If there is no dispatcher, then we treat this as not being cached.
2771-
// $FlowFixMe[incompatible-call]: We don't want to use rest arguments since we transpile the code.
2772-
return fn.apply(null, arguments);
2773-
}
2774-
2775-
var fnMap = dispatcher.getCacheForType(createCacheRoot);
2776-
var fnNode = fnMap.get(fn);
2777-
var cacheNode;
2778-
2779-
if (fnNode === undefined) {
2780-
cacheNode = createCacheNode();
2781-
fnMap.set(fn, cacheNode);
2782-
} else {
2783-
cacheNode = fnNode;
2784-
}
2785-
2786-
for (var i = 0, l = arguments.length; i < l; i++) {
2787-
var arg = arguments[i];
2788-
2789-
if (
2790-
typeof arg === "function" ||
2791-
(typeof arg === "object" && arg !== null)
2792-
) {
2793-
// Objects go into a WeakMap
2794-
var objectCache = cacheNode.o;
2795-
2796-
if (objectCache === null) {
2797-
cacheNode.o = objectCache = new WeakMap();
2798-
}
2799-
2800-
var objectNode = objectCache.get(arg);
2801-
2802-
if (objectNode === undefined) {
2803-
cacheNode = createCacheNode();
2804-
objectCache.set(arg, cacheNode);
2805-
} else {
2806-
cacheNode = objectNode;
2807-
}
2808-
} else {
2809-
// Primitives go into a regular Map
2810-
var primitiveCache = cacheNode.p;
2811-
2812-
if (primitiveCache === null) {
2813-
cacheNode.p = primitiveCache = new Map();
2814-
}
2815-
2816-
var primitiveNode = primitiveCache.get(arg);
2817-
2818-
if (primitiveNode === undefined) {
2819-
cacheNode = createCacheNode();
2820-
primitiveCache.set(arg, cacheNode);
2821-
} else {
2822-
cacheNode = primitiveNode;
2823-
}
2824-
}
2825-
}
2826-
2827-
if (cacheNode.s === TERMINATED) {
2828-
return cacheNode.v;
2829-
}
2830-
2831-
if (cacheNode.s === ERRORED) {
2832-
throw cacheNode.v;
2833-
}
2834-
2835-
try {
2836-
// $FlowFixMe[incompatible-call]: We don't want to use rest arguments since we transpile the code.
2837-
var result = fn.apply(null, arguments);
2838-
var terminatedNode = cacheNode;
2839-
terminatedNode.s = TERMINATED;
2840-
terminatedNode.v = result;
2841-
return result;
2842-
} catch (error) {
2843-
// We store the first error that's thrown and rethrow it.
2844-
var erroredNode = cacheNode;
2845-
erroredNode.s = ERRORED;
2846-
erroredNode.v = error;
2847-
throw error;
2848-
}
2759+
// $FlowFixMe[incompatible-call]: We don't want to use rest arguments since we transpile the code.
2760+
return fn.apply(null, arguments);
28492761
};
28502762
}
28512763

compiled/facebook-www/React-prod.classic.js

+2-43
Original file line numberDiff line numberDiff line change
@@ -280,12 +280,6 @@ function lazyInitializer(payload) {
280280
if (1 === payload._status) return payload._result.default;
281281
throw payload._result;
282282
}
283-
function createCacheRoot() {
284-
return new WeakMap();
285-
}
286-
function createCacheNode() {
287-
return { s: 0, v: void 0, o: null, p: null };
288-
}
289283
var ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner,
290284
RESERVED_PROPS = { key: !0, ref: !0, __self: !0, __source: !0 };
291285
function jsx$1(type, config, maybeKey) {
@@ -355,42 +349,7 @@ exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED =
355349
ReactSharedInternals;
356350
exports.cache = function (fn) {
357351
return function () {
358-
var dispatcher = ReactCurrentCache.current;
359-
if (!dispatcher) return fn.apply(null, arguments);
360-
var fnMap = dispatcher.getCacheForType(createCacheRoot);
361-
dispatcher = fnMap.get(fn);
362-
void 0 === dispatcher &&
363-
((dispatcher = createCacheNode()), fnMap.set(fn, dispatcher));
364-
fnMap = 0;
365-
for (var l = arguments.length; fnMap < l; fnMap++) {
366-
var arg = arguments[fnMap];
367-
if (
368-
"function" === typeof arg ||
369-
("object" === typeof arg && null !== arg)
370-
) {
371-
var objectCache = dispatcher.o;
372-
null === objectCache && (dispatcher.o = objectCache = new WeakMap());
373-
dispatcher = objectCache.get(arg);
374-
void 0 === dispatcher &&
375-
((dispatcher = createCacheNode()), objectCache.set(arg, dispatcher));
376-
} else
377-
(objectCache = dispatcher.p),
378-
null === objectCache && (dispatcher.p = objectCache = new Map()),
379-
(dispatcher = objectCache.get(arg)),
380-
void 0 === dispatcher &&
381-
((dispatcher = createCacheNode()),
382-
objectCache.set(arg, dispatcher));
383-
}
384-
if (1 === dispatcher.s) return dispatcher.v;
385-
if (2 === dispatcher.s) throw dispatcher.v;
386-
try {
387-
var result = fn.apply(null, arguments);
388-
fnMap = dispatcher;
389-
fnMap.s = 1;
390-
return (fnMap.v = result);
391-
} catch (error) {
392-
throw ((result = dispatcher), (result.s = 2), (result.v = error), error);
393-
}
352+
return fn.apply(null, arguments);
394353
};
395354
};
396355
exports.cloneElement = function (element, config, children) {
@@ -587,4 +546,4 @@ exports.useSyncExternalStore = function (
587546
exports.useTransition = function () {
588547
return ReactCurrentDispatcher.current.useTransition();
589548
};
590-
exports.version = "18.3.0-www-classic-7998f47a";
549+
exports.version = "18.3.0-www-classic-67c6907a";

compiled/facebook-www/React-prod.modern.js

+2-43
Original file line numberDiff line numberDiff line change
@@ -247,12 +247,6 @@ function lazyInitializer(payload) {
247247
if (1 === payload._status) return payload._result.default;
248248
throw payload._result;
249249
}
250-
function createCacheRoot() {
251-
return new WeakMap();
252-
}
253-
function createCacheNode() {
254-
return { s: 0, v: void 0, o: null, p: null };
255-
}
256250
var ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner,
257251
RESERVED_PROPS = { key: !0, ref: !0, __self: !0, __source: !0 };
258252
function jsx$1(type, config, maybeKey) {
@@ -322,42 +316,7 @@ exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED =
322316
ReactSharedInternals;
323317
exports.cache = function (fn) {
324318
return function () {
325-
var dispatcher = ReactCurrentCache.current;
326-
if (!dispatcher) return fn.apply(null, arguments);
327-
var fnMap = dispatcher.getCacheForType(createCacheRoot);
328-
dispatcher = fnMap.get(fn);
329-
void 0 === dispatcher &&
330-
((dispatcher = createCacheNode()), fnMap.set(fn, dispatcher));
331-
fnMap = 0;
332-
for (var l = arguments.length; fnMap < l; fnMap++) {
333-
var arg = arguments[fnMap];
334-
if (
335-
"function" === typeof arg ||
336-
("object" === typeof arg && null !== arg)
337-
) {
338-
var objectCache = dispatcher.o;
339-
null === objectCache && (dispatcher.o = objectCache = new WeakMap());
340-
dispatcher = objectCache.get(arg);
341-
void 0 === dispatcher &&
342-
((dispatcher = createCacheNode()), objectCache.set(arg, dispatcher));
343-
} else
344-
(objectCache = dispatcher.p),
345-
null === objectCache && (dispatcher.p = objectCache = new Map()),
346-
(dispatcher = objectCache.get(arg)),
347-
void 0 === dispatcher &&
348-
((dispatcher = createCacheNode()),
349-
objectCache.set(arg, dispatcher));
350-
}
351-
if (1 === dispatcher.s) return dispatcher.v;
352-
if (2 === dispatcher.s) throw dispatcher.v;
353-
try {
354-
var result = fn.apply(null, arguments);
355-
fnMap = dispatcher;
356-
fnMap.s = 1;
357-
return (fnMap.v = result);
358-
} catch (error) {
359-
throw ((result = dispatcher), (result.s = 2), (result.v = error), error);
360-
}
319+
return fn.apply(null, arguments);
361320
};
362321
};
363322
exports.cloneElement = function (element, config, children) {
@@ -579,4 +538,4 @@ exports.useSyncExternalStore = function (
579538
exports.useTransition = function () {
580539
return ReactCurrentDispatcher.current.useTransition();
581540
};
582-
exports.version = "18.3.0-www-modern-cd8a63c4";
541+
exports.version = "18.3.0-www-modern-14d3332b";

0 commit comments

Comments
 (0)