vike
Version:
The Framework *You* Control - Next.js & Nuxt alternative for unprecedented flexibility and dependability.
62 lines (61 loc) • 2.76 kB
JavaScript
export { getPublicProxy };
// We use a proxy instead of property getters.
// - The issue with property getters is that they can't be `writable: true` but we do want the user to be able to modify the value of internal properties.
// ```console
// TypeError: Invalid property descriptor. Cannot both specify accessors and a value or writable attribute, #<Object>
// ```
// - Previous implementation using property getters: https://github.com/vikejs/vike/blob/4dbb354b0bcec04e862041fc9183fc4691bb8711/vike/utils/makePublicCopy.ts
// Show warning when user is accessing internal `_` properties.
import { NOT_SERIALIZABLE } from './NOT_SERIALIZABLE.js';
import { assert, assertUsage, assertWarning } from '../utils/assert.js';
import { getPropAccessNotation } from '../utils/getPropAccessNotation.js';
import { isBrowser } from '../utils/isBrowser.js';
function getPublicProxy(obj, objName, skipOnInternalProp, fallback) {
return new Proxy(obj, {
get: (_, prop) => getProp(prop, obj, objName, skipOnInternalProp, fallback),
});
}
function getProp(prop, ...args) {
const [obj, objName, skipOnInternalProp, fallback] = args;
const propStr = String(prop);
if (prop === '_isProxyObject')
return true;
if (prop === 'dangerouslyUseInternals') {
args[2] = true; // skipOnInternalProp
return getPublicProxy(...args);
}
if (!skipOnInternalProp) {
if (!globalThis.__VIKE__IS_CLIENT)
onInternalProp(propStr, objName);
}
if (prop === '_originalObject')
return obj;
if (fallback && !(prop in obj)) {
// Rudimentary flat pageContext implementation https://github.com/vikejs/vike/issues/1268
// Failed full-fledged implementation: https://github.com/vikejs/vike/pull/2458
return fallback(prop);
}
const val = obj[prop];
onNotSerializable(propStr, val, objName);
return val;
}
function onNotSerializable(propStr, val, objName) {
if (val !== NOT_SERIALIZABLE)
return;
const propName = getPropAccessNotation(propStr);
assert(isBrowser());
assertUsage(false, `Can't access ${objName}${propName} on the client side. Because it can't be serialized, see server logs.`);
}
function onInternalProp(propStr, objName) {
// We must skip it on the client-side because of the reactivity mechanism of UI frameworks like Solid.
assert(!isBrowser());
// TO-DO/soon/proxy: remove this and only warn on built-in access instead
if (propStr === '_configFromHook')
return;
if (propStr.startsWith('_')) {
assertWarning(false, `Using internal ${objName}.${propStr} — https://vike.dev/warning/internals`, {
onlyOnce: true,
showStackTrace: true,
});
}
}