Skip to content

Commit

Permalink
Dedupe module id generation (facebook#20172)
Browse files Browse the repository at this point in the history
  • Loading branch information
sebmarkbage authored and koto committed Jun 15, 2021
1 parent a44e1fc commit 37778b9
Show file tree
Hide file tree
Showing 7 changed files with 37 additions and 0 deletions.
3 changes: 3 additions & 0 deletions packages/react-noop-renderer/src/ReactNoopFlightServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ const ReactNoopFlightServer = ReactFlightServer({
isModuleReference(reference: Object): boolean {
return reference.$$typeof === Symbol.for('react.module.reference');
},
getModuleKey(reference: Object): Object {
return reference;
},
resolveModuleMetaData(
config: void,
reference: {$$typeof: Symbol, value: any},
Expand Down
9 changes: 9 additions & 0 deletions packages/react-server/src/ReactFlightServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import type {
BundlerConfig,
ModuleMetaData,
ModuleReference,
ModuleKey,
} from './ReactFlightServerConfig';

import {
Expand All @@ -28,6 +29,7 @@ import {
processSymbolChunk,
processErrorChunk,
resolveModuleMetaData,
getModuleKey,
isModuleReference,
} from './ReactFlightServerConfig';

Expand Down Expand Up @@ -79,6 +81,7 @@ export type Request = {
completedJSONChunks: Array<Chunk>,
completedErrorChunks: Array<Chunk>,
writtenSymbols: Map<Symbol, number>,
writtenModules: Map<ModuleKey, number>,
flowing: boolean,
toJSON: (key: string, value: ReactModel) => ReactJSONValue,
};
Expand All @@ -101,6 +104,7 @@ export function createRequest(
completedJSONChunks: [],
completedErrorChunks: [],
writtenSymbols: new Map(),
writtenModules: new Map(),
flowing: false,
toJSON: function(key: string, value: ReactModel): ReactJSONValue {
return resolveModelToJSON(request, this, key, value);
Expand Down Expand Up @@ -425,6 +429,11 @@ export function resolveModelToJSON(
if (typeof value === 'object') {
if (isModuleReference(value)) {
const moduleReference: ModuleReference<any> = (value: any);
const moduleKey: ModuleKey = getModuleKey(moduleReference);
const existingId = request.writtenModules.get(moduleKey);
if (existingId !== undefined) {
return serializeByValueID(existingId);
}
try {
const moduleMetaData: ModuleMetaData = resolveModuleMetaData(
request.bundlerConfig,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,7 @@ declare var $$$hostConfig: any;
export opaque type BundlerConfig = mixed; // eslint-disable-line no-undef
export opaque type ModuleReference<T> = mixed; // eslint-disable-line no-undef
export opaque type ModuleMetaData: any = mixed; // eslint-disable-line no-undef
export opaque type ModuleKey: any = mixed; // eslint-disable-line no-undef
export const isModuleReference = $$$hostConfig.isModuleReference;
export const getModuleKey = $$$hostConfig.getModuleKey;
export const resolveModuleMetaData = $$$hostConfig.resolveModuleMetaData;
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ export function isModuleReference(reference: Object): boolean {
return reference instanceof JSResourceReference;
}

export type ModuleKey = ModuleReference<any>;

export function getModuleKey(reference: ModuleReference<any>): ModuleKey {
// We use the reference object itself as the key because we assume the
// object will be cached by the bundler runtime.
return reference;
}

export function resolveModuleMetaData<T>(
config: BundlerConfig,
resource: ModuleReference<T>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,14 @@ export type ModuleMetaData = {
name: string,
};

export type ModuleKey = string;

const MODULE_TAG = Symbol.for('react.module.reference');

export function getModuleKey(reference: ModuleReference<any>): ModuleKey {
return reference.name;
}

export function isModuleReference(reference: Object): boolean {
return reference.$$typeof === MODULE_TAG;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ export function isModuleReference(reference: Object): boolean {
return reference instanceof JSResourceReferenceImpl;
}

export type ModuleKey = ModuleReference<any>;

export function getModuleKey(reference: ModuleReference<any>): ModuleKey {
// We use the reference object itself as the key because we assume the
// object will be cached by the bundler runtime.
return reference;
}

export function resolveModuleMetaData<T>(
config: BundlerConfig,
resource: ModuleReference<T>,
Expand Down
1 change: 1 addition & 0 deletions scripts/jest/setupHostConfigs.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ jest.mock('react-server/flight', () => {
jest.mock(shimServerFormatConfigPath, () => config);
jest.mock('react-server/src/ReactFlightServerBundlerConfigCustom', () => ({
isModuleReference: config.isModuleReference,
getModuleKey: config.getModuleKey,
resolveModuleMetaData: config.resolveModuleMetaData,
}));
jest.mock(shimFlightServerConfigPath, () =>
Expand Down

0 comments on commit 37778b9

Please sign in to comment.