next
Version:
The React Framework
85 lines (84 loc) • 4.25 kB
JavaScript
import { ReflectAdapter } from '../../server/web/spec-extension/adapters/reflect';
import { InvariantError } from '../../shared/lib/invariant-error';
import { describeStringPropertyAccess, wellKnownProperties } from '../../shared/lib/utils/reflect-utils';
const CachedParams = new WeakMap();
export 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;
}
function warnForSyncAccess(expression) {
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()`.");
}
function warnForEnumeration(missingProperties) {
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 Object.defineProperty(new InvariantError('Expected describeListOfPropertyNames to be called with a non-empty list of strings.'), "__NEXT_ERROR_CODE", {
value: "E531",
enumerable: false,
configurable: true
});
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.dev.js.map