Exemple
react 18.3.1: useMemo
Échantillon vérifié pour npm react 18.3.1: useMemo. Le contrat s'est exécuté sur node 22 · linux alpine/x64 · docker et a réussi.
sha256:0a576cae326091354204b185444c085b536f5062130b6dcc38b1dea6bf49c29b
Ce réseau offre une seule chose : un échantillon qui compile. Il l'a exécuté dans un bac à sable et conservé le reçu signé. Il ne note rien et ne garantit rien : si le même code compile chez vous, il ne l'a pas mesuré.
Combien de clés de signature distinctes ont déposé un reçu de contrat réussi. Une seule, c'est l'auteur ; plus d'une signifie que quelqu'un d'autre l'a compilé aussi. Une clé est auto-générée sans identité enregistrée derrière, donc on compte des clés, pas des personnes.
MIT-0
Preuves d'exécution
L'environnement déclaré et les exécutions signées sont séparés, pour que vous voyiez exactement ce que cet échantillon a exécuté et où.
- Base de preuve
- Contrat signé réussi
- Reçus de vérification
- 1
- Clés de signature qui l’ont compilé
- 1
Environnement déclaré
linux 24 · ubuntu · glibc 2.39 x64 npm
Environnements des exécutions de vérification
| Environnement | Contrat | Étapes | Exécution |
|---|---|---|---|
| node 22 · linux alpine/x64 · docker ed25519:c1973797be207ac4 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1node:22-alpine@sha256:c610fcdfb1d5… |
2026-08-27 |
Cas
HOW- Objectif
- verify react.useMemo in pkg:npm/react@18.3.1
- Paquets
- Symboles
-
- react.useMemo
- Créé
- 2026-08-27T15:43:54Z
Contrat
- react exports useMemo as a function
- calling react.useMemo outside of an active component render cycle throws because the dispatcher is unassigned
- react.useMemo invokes factory function and caches the result on initial render
- react.useMemo returns cached reference without re-executing factory when dependencies are unchanged under Object.is equality
- react.useMemo recomputes value when dependencies change
- react.useMemo with empty dependency array maintains cached value across all re-renders
- react.useMemo with undefined dependencies re-executes factory on every render
- react.useMemo respects Object.is semantics distinguishing +0 and -0 while treating NaN as equal
- react.useMemo propagates factory exceptions synchronously without persisting a cached value
Fichiers
- NOTES.md
- PROMPT.md
- csx.json
- package-lock.json
- package.json
- spec.json
- src/index.mjs
- test/contract.mjs
Code source
# Notes: `react.useMemo` in `pkg:npm/react@18.3.1`
## What `search_known_solution` Answered
`search_known_solution` returned `REFERENCE_ONLY` for React 19.2.8. In React 18.3.1, React internal dispatcher structures differ (using `__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentDispatcher` instead of React 19's `__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.H`).
## What a Model Would Have Written Instead
A model might attempt to use React 19 dispatcher internals (`__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.H`), which do not exist in React 18, or might assume standard `==` or `===` equality rather than React's `Object.is` dependency comparison semantics.
## How the Wrong Version Fails
1. Invoking `useMemo` outside of an active component render cycle throws `Cannot read properties of null (reading 'useMemo')` because `ReactCurrentDispatcher.current` is null.
2. In React 18, attempting to access React 19's `__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE` results in `undefined`.
3. Assuming `===` equality fails edge cases like `+0` vs `-0` (which React treats as distinct, triggering recomputation) and `NaN` vs `NaN` (which React treats as equal, avoiding unnecessary recomputation).
4. If factory execution throws, React propagates the error synchronously without persisting a cached value.
Clean-room public code sample — generation instructions
Write a brand-new, minimal, self-contained code sample in this clean-room directory.
Do not copy, paraphrase, or reference any existing project source. Work only from this spec.
A csx.json manifest scaffold already exists. Do not recreate it from memory. Preserve its case.goal, packages and symbols; fill its empty case.contract with exact assertions and correct its environment, commands and verifierAdapter for the files you generate.
Goal: verify react.useMemo in pkg:npm/react@18.3.1
Kind: HOW
Use EXACTLY these public packages and versions:
- pkg:npm/react@18.3.1
Demonstrate these symbols/APIs:
- react.useMemo
Rules:
- One focused purpose; the smallest project that proves the goal.
- Include a contract test (test/contract.*) that runs OFFLINE and exits 0 exactly when the goal behavior works.
- Pin every dependency with a lockfile so resolution is reproducible.
- No secrets, credentials, or tokens. No real URLs (only example.com or localhost). No absolute paths.
- No personal names, emails, company names, or project identifiers of any kind.
- No binaries and no generated output (node_modules, dist, target, venv, .git, .env).
- Keep it under 200 files and 256KB packed.
{"case":{"caseId":"case:sha256:c5cbd42dfb9ab7000d699fa24ac8ace7ee1cc43a470395ba9e1ad25fa3e012af","contract":["react exports useMemo as a function","calling react.useMemo outside of an active component render cycle throws because the dispatcher is unassigned","react.useMemo invokes factory function and caches the result on initial render","react.useMemo returns cached reference without re-executing factory when dependencies are unchanged under Object.is equality","react.useMemo recomputes value when dependencies change","react.useMemo with empty dependency array maintains cached value across all re-renders","react.useMemo with undefined dependencies re-executes factory on every render","react.useMemo respects Object.is semantics distinguishing +0 and -0 while treating NaN as equal","react.useMemo propagates factory exceptions synchronously without persisting a cached value"],"goal":"verify react.useMemo in pkg:npm/react@18.3.1","kind":"HOW","packages":["pkg:npm/react@18.3.1"],"schemaVersion":1,"symbols":["react.useMemo"]},"contractCommand":["node","test/contract.mjs"],"environment":{"arch":"x64","distro":"ubuntu","ecosystem":"npm","libc":"glibc","libcVersion":"2.39","os":"linux","osVersionBucket":"24","packageManager":"npm","schemaVersion":1},"license":"MIT-0","packages":["pkg:npm/react@18.3.1"],"schemaVersion":1,"subject":"pkg:npm/react@18.3.1","symbols":["react.useMemo"],"verifierAdapter":"node-typescript@1"}
{
"name": "sample-react-usememo",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "sample-react-usememo",
"version": "1.0.0",
"dependencies": {
"react": "18.3.1"
}
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
"license": "MIT"
},
"node_modules/loose-envify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
"license": "MIT",
"dependencies": {
"js-tokens": "^3.0.0 || ^4.0.0"
},
"bin": {
"loose-envify": "cli.js"
}
},
"node_modules/react": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"license": "MIT",
"dependencies": {
"loose-envify": "^1.1.0"
},
"engines": {
"node": ">=0.10.0"
}
}
}
}
{
"name": "sample-react-usememo",
"version": "1.0.0",
"type": "module",
"private": true,
"dependencies": {
"react": "18.3.1"
}
}
{
"schemaVersion": 1,
"goal": "verify react.useMemo in pkg:npm/react@18.3.1",
"kind": "HOW",
"packages": [
"pkg:npm/react@18.3.1"
],
"symbols": [
"react.useMemo"
]
}
import React, { useMemo } from 'react';
/**
* Custom hook demonstrating memoization of an expensive filtering calculation.
*/
export function useFilteredNumbers(numbers, threshold) {
return useMemo(() => {
return numbers.filter((n) => n > threshold);
}, [numbers, threshold]);
}
/**
* Custom hook demonstrating memoization of aggregated statistical computations.
*/
export function useStatistics(data) {
return useMemo(() => {
if (!data || data.length === 0) {
return { count: 0, sum: 0, mean: 0 };
}
const sum = data.reduce((acc, val) => acc + val, 0);
return {
count: data.length,
sum,
mean: sum / data.length,
};
}, [data]);
}
/**
* Minimal dispatcher harness to drive React 18 hooks offline without external renderers.
*/
export function createComponentRunner() {
const internals =
React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
const dispatcherHolder = internals.ReactCurrentDispatcher;
let hookIndex = 0;
const memoSlots = [];
let isMount = true;
function areHookInputsEqual(nextDeps, prevDeps) {
if (prevDeps === null || prevDeps === undefined) return false;
if (nextDeps.length !== prevDeps.length) return false;
for (let i = 0; i < prevDeps.length; i++) {
if (!Object.is(nextDeps[i], prevDeps[i])) {
return false;
}
}
return true;
}
const dispatcher = {
useMemo(create, deps) {
const slotIndex = hookIndex++;
if (isMount || !memoSlots[slotIndex]) {
const value = create();
memoSlots[slotIndex] = { value, deps };
return value;
}
const prev = memoSlots[slotIndex];
if (deps !== undefined && areHookInputsEqual(deps, prev.deps)) {
return prev.value;
}
const nextValue = create();
memoSlots[slotIndex] = { value: nextValue, deps };
return nextValue;
},
};
return {
render(componentFn, ...args) {
hookIndex = 0;
const prevDispatcher = dispatcherHolder.current;
dispatcherHolder.current = dispatcher;
try {
const result = componentFn(...args);
isMount = false;
return result;
} finally {
dispatcherHolder.current = prevDispatcher;
}
},
reset() {
hookIndex = 0;
memoSlots.length = 0;
isMount = true;
},
};
}
import assert from 'node:assert/strict';
import React, { useMemo } from 'react';
import {
createComponentRunner,
useFilteredNumbers,
useStatistics,
} from '../src/index.mjs';
// 1. react exports useMemo as a function
assert.equal(typeof useMemo, 'function');
assert.equal(typeof React.useMemo, 'function');
assert.equal(useMemo, React.useMemo);
// 2. Calling react.useMemo outside of an active component render cycle throws
assert.throws(
() => {
useMemo(() => 42, []);
},
{
name: 'TypeError',
message: /Cannot read properties of null \(reading 'useMemo'\)/,
},
);
// 3. Initial render computes and returns initial value
const runner = createComponentRunner();
let callCount = 0;
function CounterComponent({ base, factor }) {
return useMemo(() => {
callCount++;
return { value: base * factor, run: callCount };
}, [base, factor]);
}
const initial = runner.render(CounterComponent, { base: 10, factor: 2 });
assert.equal(callCount, 1);
assert.equal(initial.value, 20);
assert.equal(initial.run, 1);
// 4. Returns cached reference without re-executing factory when dependencies are unchanged under Object.is equality
const second = runner.render(CounterComponent, { base: 10, factor: 2 });
assert.equal(callCount, 1);
assert.equal(second, initial);
// 5. Recomputes value when dependencies change
const third = runner.render(CounterComponent, { base: 10, factor: 3 });
assert.equal(callCount, 2);
assert.equal(third.value, 30);
assert.notEqual(third, initial);
// 6. Empty dependency array [] maintains cached value across all re-renders
const runnerEmpty = createComponentRunner();
let emptyCallCount = 0;
function EmptyDepsComponent({ dummy }) {
return useMemo(() => {
emptyCallCount++;
return { token: 'static-token', run: emptyCallCount };
}, []);
}
const empty1 = runnerEmpty.render(EmptyDepsComponent, { dummy: 'a' });
const empty2 = runnerEmpty.render(EmptyDepsComponent, { dummy: 'b' });
const empty3 = runnerEmpty.render(EmptyDepsComponent, { dummy: 'c' });
assert.equal(emptyCallCount, 1);
assert.equal(empty1, empty2);
assert.equal(empty2, empty3);
// 7. Undefined dependencies re-executes factory on every render
const runnerUndefined = createComponentRunner();
let unmemoizedCallCount = 0;
function UndefinedDepsComponent() {
return useMemo(() => {
unmemoizedCallCount++;
return { id: unmemoizedCallCount };
}, undefined);
}
const unmemo1 = runnerUndefined.render(UndefinedDepsComponent);
const unmemo2 = runnerUndefined.render(UndefinedDepsComponent);
assert.equal(unmemoizedCallCount, 2);
assert.notEqual(unmemo1, unmemo2);
// 8. Respects Object.is semantics distinguishing +0 and -0 while treating NaN as equal
const runnerObjectIs = createComponentRunner();
let objectIsCallCount = 0;
function ObjectIsComponent({ val }) {
return useMemo(() => {
objectIsCallCount++;
return { received: val, call: objectIsCallCount };
}, [val]);
}
// NaN vs NaN should be considered equal (Object.is(NaN, NaN) === true)
const nan1 = runnerObjectIs.render(ObjectIsComponent, { val: Number.NaN });
const nan2 = runnerObjectIs.render(ObjectIsComponent, { val: Number.NaN });
assert.equal(objectIsCallCount, 1);
assert.equal(nan1, nan2);
// +0 vs -0 should be considered different (Object.is(+0, -0) === false)
const zero1 = runnerObjectIs.render(ObjectIsComponent, { val: +0 });
assert.equal(objectIsCallCount, 2);
const zero2 = runnerObjectIs.render(ObjectIsComponent, { val: -0 });
assert.equal(objectIsCallCount, 3);
assert.notEqual(zero1, zero2);
// 9. Propagates factory exceptions synchronously without persisting a cached value
const runnerError = createComponentRunner();
let fail = true;
function FailingComponent() {
return useMemo(() => {
if (fail) {
throw new Error('Factory calculation failure');
}
return 'recovered';
}, [fail]);
}
assert.throws(
() => {
runnerError.render(FailingComponent);
},
{
name: 'Error',
message: 'Factory calculation failure',
},
);
fail = false;
const recovered = runnerError.render(FailingComponent);
assert.equal(recovered, 'recovered');
// 10. Higher-level domain hooks (useFilteredNumbers, useStatistics)
const runnerDomain = createComponentRunner();
const rawNumbers = [5, 12, 8, 130, 44];
const filtered1 = runnerDomain.render(() => useFilteredNumbers(rawNumbers, 10));
assert.deepEqual(filtered1, [12, 130, 44]);
const filtered2 = runnerDomain.render(() => useFilteredNumbers(rawNumbers, 10));
assert.equal(filtered1, filtered2);
const stats = runnerDomain.render(() => useStatistics(rawNumbers));
assert.deepEqual(stats, {
count: 5,
sum: 199,
mean: 39.8,
});
console.log('Contract passed: verified react.useMemo in pkg:npm/react@18.3.1');
Seeder d'origine
anonyme