Skip to content

Commit

Permalink
useFormState: Hash the component key path for more compact output (#2…
Browse files Browse the repository at this point in the history
…7397)

To support MPA-style form submissions, useFormState sends down a key
that represents the identity of the hook on the page. It's based on the
key path of the component within the React tree; for deeply nested
hooks, this keypath can become very long. We can hash the key to make it
shorter.

Adds a method called createFastHash to the Stream Config interface.
We're not using this for security or obfuscation, only to generate a
more compact key without sacrificing too much collision resistance.

- In Node.js builds, createFastHash uses the built-in crypto module.
- In Bun builds, createFastHash uses Bun.hash. See:
https://bun.sh/docs/api/hashing#bun-hash

I have not yet implemented createFastHash in the Edge, Browser, or FB
(Hermes) stream configs because those environments do not have a
built-in hashing function that meets our requirements. (We can't use the
web standard `crypto` API because those methods are async, and yielding
to the main thread is too costly to be worth it for this particular use
case.) We'll likely use a pure JS implementation in those environments;
for now, they just return the original string without hashing it. I'll
address this in separate PRs.

DiffTrain build for [2b3d582](2b3d582)
  • Loading branch information
acdlite committed Sep 20, 2023
1 parent ca0b9f4 commit ab9d541
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 10 deletions.
2 changes: 1 addition & 1 deletion compiled/facebook-www/REVISION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1f4936660dcaba2e5722013f0ad12d7369543a9f
2b3d5826836ac59f8446281976762d594e55d97e
14 changes: 11 additions & 3 deletions compiled/facebook-www/ReactDOMServer-dev.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ if (__DEV__) {
var React = require("react");
var ReactDOM = require("react-dom");

var ReactVersion = "18.3.0-www-classic-cc6e6575";
var ReactVersion = "18.3.0-www-classic-8b1a4ace";

// This refers to a WWW module.
var warningWWW = require("warning");
Expand Down Expand Up @@ -108,6 +108,9 @@ function closeWithError(destination, error) {
// $FlowFixMe[incompatible-call]: This is an Error object or the destination accepts other types.
destination.destroy(error);
}
function createFastHash(input) {
return input;
}

var assign = Object.assign;

Expand Down Expand Up @@ -9477,11 +9480,16 @@ function useOptimistic(passthrough, reducer) {

function createPostbackFormStateKey(permalink, componentKeyPath, hookIndex) {
if (permalink !== undefined) {
// Don't bother to hash a permalink-based key since it's already short.
return "p" + permalink;
} else {
// Append a node to the key path that represents the form state hook.
var keyPath = [componentKeyPath, null, hookIndex];
return "k" + JSON.stringify(keyPath);
var keyPath = [componentKeyPath, null, hookIndex]; // Key paths are hashed to reduce the size. It does not need to be secure,
// and it's more important that it's fast than that it's completely
// collision-free.

var keyPathHash = createFastHash(JSON.stringify(keyPath));
return "k" + keyPathHash;
}
}

Expand Down
14 changes: 11 additions & 3 deletions compiled/facebook-www/ReactDOMServer-dev.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ if (__DEV__) {
var React = require("react");
var ReactDOM = require("react-dom");

var ReactVersion = "18.3.0-www-modern-016e469a";
var ReactVersion = "18.3.0-www-modern-1505778a";

// This refers to a WWW module.
var warningWWW = require("warning");
Expand Down Expand Up @@ -108,6 +108,9 @@ function closeWithError(destination, error) {
// $FlowFixMe[incompatible-call]: This is an Error object or the destination accepts other types.
destination.destroy(error);
}
function createFastHash(input) {
return input;
}

var assign = Object.assign;

Expand Down Expand Up @@ -9236,11 +9239,16 @@ function useOptimistic(passthrough, reducer) {

function createPostbackFormStateKey(permalink, componentKeyPath, hookIndex) {
if (permalink !== undefined) {
// Don't bother to hash a permalink-based key since it's already short.
return "p" + permalink;
} else {
// Append a node to the key path that represents the form state hook.
var keyPath = [componentKeyPath, null, hookIndex];
return "k" + JSON.stringify(keyPath);
var keyPath = [componentKeyPath, null, hookIndex]; // Key paths are hashed to reduce the size. It does not need to be secure,
// and it's more important that it's fast than that it's completely
// collision-free.

var keyPathHash = createFastHash(JSON.stringify(keyPath));
return "k" + keyPathHash;
}
}

Expand Down
12 changes: 10 additions & 2 deletions compiled/facebook-www/ReactDOMServerStreaming-dev.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ function closeWithError(destination, error) {
destination.fatal = true;
destination.error = error;
}
function createFastHash(input) {
return input;
}

var assign = Object.assign;

Expand Down Expand Up @@ -9122,11 +9125,16 @@ function useOptimistic(passthrough, reducer) {

function createPostbackFormStateKey(permalink, componentKeyPath, hookIndex) {
if (permalink !== undefined) {
// Don't bother to hash a permalink-based key since it's already short.
return "p" + permalink;
} else {
// Append a node to the key path that represents the form state hook.
var keyPath = [componentKeyPath, null, hookIndex];
return "k" + JSON.stringify(keyPath);
var keyPath = [componentKeyPath, null, hookIndex]; // Key paths are hashed to reduce the size. It does not need to be secure,
// and it's more important that it's fast than that it's completely
// collision-free.

var keyPathHash = createFastHash(JSON.stringify(keyPath));
return "k" + keyPathHash;
}
}

Expand Down
2 changes: 1 addition & 1 deletion compiled/facebook-www/ReactTestRenderer-dev.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -24360,7 +24360,7 @@ function createFiberRoot(
return root;
}

var ReactVersion = "18.3.0-www-modern-6126abbd";
var ReactVersion = "18.3.0-www-modern-27dc20d3";

// Might add PROFILE later.

Expand Down

0 comments on commit ab9d541

Please sign in to comment.