source: node_modules/ts-mixer/dist/cjs/proxy.js

main
Last change on this file was d24f17c, checked in by Aleksandar Panovski <apano77@…>, 15 months ago

Initial commit

  • Property mode set to 100644
File size: 3.8 KB
Line 
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.softMixProtos = exports.proxyMix = exports.getIngredientWithProp = void 0;
4const util_1 = require("./util");
5/**
6 * Finds the ingredient with the given prop, searching in reverse order and breadth-first if searching ingredient
7 * prototypes is required.
8 */
9const getIngredientWithProp = (prop, ingredients) => {
10 const protoChains = ingredients.map(ingredient => (0, util_1.protoChain)(ingredient));
11 // since we search breadth-first, we need to keep track of our depth in the prototype chains
12 let protoDepth = 0;
13 // not all prototype chains are the same depth, so this remains true as long as at least one of the ingredients'
14 // prototype chains has an object at this depth
15 let protosAreLeftToSearch = true;
16 while (protosAreLeftToSearch) {
17 // with the start of each horizontal slice, we assume this is the one that's deeper than any of the proto chains
18 protosAreLeftToSearch = false;
19 // scan through the ingredients right to left
20 for (let i = ingredients.length - 1; i >= 0; i--) {
21 const searchTarget = protoChains[i][protoDepth];
22 if (searchTarget !== undefined && searchTarget !== null) {
23 // if we find something, this is proof that this horizontal slice potentially more objects to search
24 protosAreLeftToSearch = true;
25 // eureka, we found it
26 if (Object.getOwnPropertyDescriptor(searchTarget, prop) != undefined) {
27 return protoChains[i][0];
28 }
29 }
30 }
31 protoDepth++;
32 }
33 return undefined;
34};
35exports.getIngredientWithProp = getIngredientWithProp;
36/**
37 * "Mixes" ingredients by wrapping them in a Proxy. The optional prototype argument allows the mixed object to sit
38 * downstream of an existing prototype chain. Note that "properties" cannot be added, deleted, or modified.
39 */
40const proxyMix = (ingredients, prototype = Object.prototype) => new Proxy({}, {
41 getPrototypeOf() {
42 return prototype;
43 },
44 setPrototypeOf() {
45 throw Error('Cannot set prototype of Proxies created by ts-mixer');
46 },
47 getOwnPropertyDescriptor(_, prop) {
48 return Object.getOwnPropertyDescriptor((0, exports.getIngredientWithProp)(prop, ingredients) || {}, prop);
49 },
50 defineProperty() {
51 throw new Error('Cannot define new properties on Proxies created by ts-mixer');
52 },
53 has(_, prop) {
54 return (0, exports.getIngredientWithProp)(prop, ingredients) !== undefined || prototype[prop] !== undefined;
55 },
56 get(_, prop) {
57 return ((0, exports.getIngredientWithProp)(prop, ingredients) || prototype)[prop];
58 },
59 set(_, prop, val) {
60 const ingredientWithProp = (0, exports.getIngredientWithProp)(prop, ingredients);
61 if (ingredientWithProp === undefined)
62 throw new Error('Cannot set new properties on Proxies created by ts-mixer');
63 ingredientWithProp[prop] = val;
64 return true;
65 },
66 deleteProperty() {
67 throw new Error('Cannot delete properties on Proxies created by ts-mixer');
68 },
69 ownKeys() {
70 return ingredients
71 .map(Object.getOwnPropertyNames)
72 .reduce((prev, curr) => curr.concat(prev.filter(key => curr.indexOf(key) < 0)));
73 },
74});
75exports.proxyMix = proxyMix;
76/**
77 * Creates a new proxy-prototype object that is a "soft" mixture of the given prototypes. The mixing is achieved by
78 * proxying all property access to the ingredients. This is not ES5 compatible and less performant. However, any
79 * changes made to the source prototypes will be reflected in the proxy-prototype, which may be desirable.
80 */
81const softMixProtos = (ingredients, constructor) => (0, exports.proxyMix)([...ingredients, { constructor }]);
82exports.softMixProtos = softMixProtos;
Note: See TracBrowser for help on using the repository browser.