@netlify/content-engine
Version:
135 lines • 4.63 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.enableNodeMutationsDetection = enableNodeMutationsDetection;
exports.wrapNode = wrapNode;
exports.wrapNodes = wrapNodes;
const reporter_1 = __importDefault(require("../reporter"));
const stack_trace_utils_1 = require("./stack-trace-utils");
const reported = new Set();
const genericProxy = createProxyHandler();
const nodeInternalProxy = createProxyHandler({
onGet(key, value) {
if (key === `fieldOwners` || key === `content`) {
// all allowed in here
return value;
}
return undefined;
},
onSet(target, key, value) {
if (key === `fieldOwners` || key === `content`) {
target[key] = value;
return true;
}
return undefined;
},
});
const nodeProxy = createProxyHandler({
onGet(key, value) {
if (key === `internal`) {
return memoizedProxy(value, nodeInternalProxy);
}
else if (key === `fields` || key === `children`) {
// all allowed in here
return value;
}
return undefined;
},
onSet(target, key, value) {
if (key === `fields` || key === `children`) {
target[key] = value;
return true;
}
return undefined;
},
});
/**
* Every time we create proxy for object, we store it in WeakMap,
* so that we reuse it for that object instead of creating new Proxy.
* This also ensures reference equality: `memoizedProxy(obj) === memoizedProxy(obj)`.
* If we didn't reuse already created proxy above comparison would return false.
*/
const referenceMap = new WeakMap();
function memoizedProxy(target, handler) {
const alreadyWrapped = referenceMap.get(target);
if (alreadyWrapped) {
return alreadyWrapped;
}
else {
const wrapped = new Proxy(target, handler);
referenceMap.set(target, wrapped);
return wrapped;
}
}
function createProxyHandler({ onGet, onSet, } = {}) {
function set(target, key, value) {
if (onSet) {
const result = onSet(target, key, value);
if (result !== undefined) {
return result;
}
}
const error = new Error(`Stack trace:`);
Error.captureStackTrace(error, set);
if (error.stack && !reported.has(error.stack)) {
reported.add(error.stack);
const codeFrame = (0, stack_trace_utils_1.getNonGatsbyCodeFrameFormatted)({
stack: error.stack,
});
reporter_1.default.warn(`Node mutation detected\n\n${codeFrame ? `${codeFrame}\n\n` : ``}${error.stack.replace(/^Error:?\s*/, ``)}`);
}
return true;
}
function get(target, key) {
const value = target[key];
if (onGet) {
const result = onGet(key, value);
if (result !== undefined) {
return result;
}
}
const fieldDescriptor = Object.getOwnPropertyDescriptor(target, key);
if (fieldDescriptor && !fieldDescriptor.writable) {
// this is to prevent errors like:
// ```
// TypeError: 'get' on proxy: property 'constants' is a read - only and
// non - configurable data property on the proxy target but the proxy
// did not return its actual value
// (expected '[object Object]' but got '[object Object]')
// ```
return value;
}
if (typeof value === `object` && value !== null) {
return memoizedProxy(value, genericProxy);
}
return value;
}
return {
get,
set,
};
}
let shouldWrapNodesInProxies = !!process.env.GATSBY_DETECT_NODE_MUTATIONS;
function enableNodeMutationsDetection() {
shouldWrapNodesInProxies = true;
reporter_1.default.warn(`Node mutation detection is enabled. Remember to disable it after you are finished with diagnostic as it will cause build performance degradation.`);
}
function wrapNode(node) {
if (node && shouldWrapNodesInProxies) {
return memoizedProxy(node, nodeProxy);
}
else {
return node;
}
}
function wrapNodes(nodes) {
if (nodes && shouldWrapNodesInProxies && nodes.length > 0) {
return nodes.map((node) => memoizedProxy(node, nodeProxy));
}
else {
return nodes;
}
}
//# sourceMappingURL=detect-node-mutations.js.map
;