next
Version:
The React Framework
113 lines (112 loc) • 5.33 kB
JavaScript
import { ReflectAdapter } from '../web/spec-extension/adapters/reflect';
import { InvariantError } from '../../shared/lib/invariant-error';
import { describeStringPropertyAccess, wellKnownProperties } from './utils';
export function createRenderParamsFromClient(underlyingParams) {
if (process.env.NODE_ENV === 'development') {
return makeDynamicallyTrackedExoticParamsWithDevWarnings(underlyingParams);
} else {
return makeUntrackedExoticParams(underlyingParams);
}
}
const CachedParams = new WeakMap();
function makeUntrackedExoticParams(underlyingParams) {
const cachedParams = CachedParams.get(underlyingParams);
if (cachedParams) {
return cachedParams;
}
const promise = Promise.resolve(underlyingParams);
CachedParams.set(underlyingParams, promise);
Object.keys(underlyingParams).forEach((prop)=>{
if (wellKnownProperties.has(prop)) {
// These properties cannot be shadowed because they need to be the
// true underlying value for Promises to work correctly at runtime
} else {
;
promise[prop] = underlyingParams[prop];
}
});
return promise;
}
function makeDynamicallyTrackedExoticParamsWithDevWarnings(underlyingParams) {
const cachedParams = CachedParams.get(underlyingParams);
if (cachedParams) {
return cachedParams;
}
// We don't use makeResolvedReactPromise here because params
// supports copying with spread and we don't want to unnecessarily
// instrument the promise with spreadable properties of ReactPromise.
const promise = Promise.resolve(underlyingParams);
const proxiedProperties = new Set();
const unproxiedProperties = [];
Object.keys(underlyingParams).forEach((prop)=>{
if (wellKnownProperties.has(prop)) {
// These properties cannot be shadowed because they need to be the
// true underlying value for Promises to work correctly at runtime
} else {
proxiedProperties.add(prop);
promise[prop] = underlyingParams[prop];
}
});
const proxiedPromise = new Proxy(promise, {
get (target, prop, receiver) {
if (typeof prop === 'string') {
if (// We are accessing a property that was proxied to the promise instance
proxiedProperties.has(prop)) {
const expression = describeStringPropertyAccess('params', prop);
warnForSyncAccess(expression);
}
}
return ReflectAdapter.get(target, prop, receiver);
},
set (target, prop, value, receiver) {
if (typeof prop === 'string') {
proxiedProperties.delete(prop);
}
return ReflectAdapter.set(target, prop, value, receiver);
},
ownKeys (target) {
warnForEnumeration(unproxiedProperties);
return Reflect.ownKeys(target);
}
});
CachedParams.set(underlyingParams, proxiedPromise);
return proxiedPromise;
}
const noop = ()=>{};
const warnForSyncAccess = process.env.__NEXT_DISABLE_SYNC_DYNAMIC_API_WARNINGS ? noop : function warnForSyncAccess(expression) {
if (process.env.__NEXT_DISABLE_SYNC_DYNAMIC_API_WARNINGS) {
return;
}
console.error(`A param property was accessed directly with ${expression}. \`params\` is now a Promise and should be unwrapped with \`React.use()\` before accessing properties of the underlying params object. In this version of Next.js direct access to param properties is still supported to facilitate migration but in a future version you will be required to unwrap \`params\` with \`React.use()\`.`);
};
const warnForEnumeration = process.env.__NEXT_DISABLE_SYNC_DYNAMIC_API_WARNINGS ? noop : function warnForEnumeration(missingProperties) {
if (process.env.__NEXT_DISABLE_SYNC_DYNAMIC_API_WARNINGS) {
return;
}
if (missingProperties.length) {
const describedMissingProperties = describeListOfPropertyNames(missingProperties);
console.error(`params are being enumerated incompletely missing these properties: ${describedMissingProperties}. ` + `\`params\` should be unwrapped with \`React.use()\` before using its value. ` + `Learn more: https://nextjs.org/docs/messages/sync-dynamic-apis`);
} else {
console.error(`params are being enumerated. ` + `\`params\` should be unwrapped with \`React.use()\` before using its value. ` + `Learn more: https://nextjs.org/docs/messages/sync-dynamic-apis`);
}
};
function describeListOfPropertyNames(properties) {
switch(properties.length){
case 0:
throw new InvariantError('Expected describeListOfPropertyNames to be called with a non-empty list of strings.');
case 1:
return `\`${properties[0]}\``;
case 2:
return `\`${properties[0]}\` and \`${properties[1]}\``;
default:
{
let description = '';
for(let i = 0; i < properties.length - 1; i++){
description += `\`${properties[i]}\`, `;
}
description += `, and \`${properties[properties.length - 1]}\``;
return description;
}
}
}
//# sourceMappingURL=params.browser.js.map