From 8696da1a4e09bac6a5116c7f15ed8d2b476b1ccf Mon Sep 17 00:00:00 2001 From: Pedro Gallardo Date: Sun, 27 Aug 2023 19:14:48 -0300 Subject: [PATCH] fix: ajusta lib --- src/Emulator.ts | 8 ++++++-- src/lib/constructor.spec.ts | 11 +++++++---- src/lib/constructor.ts | 5 ++++- src/lib/methods/include.spec.ts | 27 ++++++++++++++++++++------- src/lib/methods/include.ts | 31 +++++++++++++++++++++++-------- src/types/Exotic.ts | 5 +++-- src/utils/createProxy.ts | 31 +++++++++++++++++++------------ src/utils/decode.ts | 5 ++++- src/utils/revokeProxy.ts | 6 ++++-- src/utils/traps/apply.ts | 11 +---------- src/utils/traps/construct.ts | 4 ++-- src/utils/traps/get.ts | 2 +- 12 files changed, 94 insertions(+), 52 deletions(-) diff --git a/src/Emulator.ts b/src/Emulator.ts index d8444f0..403057c 100755 --- a/src/Emulator.ts +++ b/src/Emulator.ts @@ -70,8 +70,12 @@ export default class Emulator extends EventEmitter implements Exotic.Emulator { return lib.methods.revokeAll(this); } - include(origin: Exotic.proxy.origin, target?: any): any { - return lib.methods.include(this, origin, target); + include( + encodedProxy: string, + origin: Exotic.proxy.origin, + target?: any, + ): any { + return lib.methods.include(this, encodedProxy, origin, target); } getId(value: any): number { diff --git a/src/lib/constructor.spec.ts b/src/lib/constructor.spec.ts index 9ba4080..964b93f 100644 --- a/src/lib/constructor.spec.ts +++ b/src/lib/constructor.spec.ts @@ -4,16 +4,19 @@ import { map } from "../utils"; describe("(constructor)", () => { it("Creates a new emulator", () => { - const config: Exotic.emulator.options = { traceErrors: false }; + const config: Exotic.emulator.options = { + traceErrors: false, + }; const emulator = new Emulator(config); const data: Record = map.emulators.get(emulator) || {}; - const dataProps = ["options", "refs", "counter", "proxySet"]; - const { options, refs, counter } = data; + const dataProps = ["options", "refs", "links", "counter", "proxySet"]; + const { options, refs, links, counter } = data; expect(map.emulators.has(emulator)).toBe(true); expect(Object.keys(data)).toEqual(dataProps); expect(options).toEqual(config); - expect(Reflect.ownKeys(refs).length).toBe(0); + expect(Object.keys(refs).length).toBe(0); + expect(Object.keys(links).length).toBe(0); expect(counter).toBe(0); }); }); diff --git a/src/lib/constructor.ts b/src/lib/constructor.ts index 5506ba7..93467ba 100644 --- a/src/lib/constructor.ts +++ b/src/lib/constructor.ts @@ -6,13 +6,16 @@ export default function constructor( options?: Exotic.emulator.options, ): void { // set config defaults - const config = { traceErrors: false }; + const config: Exotic.emulator.options = { + traceErrors: false, + }; if (options) { Object.assign(config, options); } const data: Exotic.emulator.data = { options: config, refs: Object.create(null), + links: Object.create(null), counter: 0, proxySet: new Set(), }; diff --git a/src/lib/methods/include.spec.ts b/src/lib/methods/include.spec.ts index c4f6c7b..38b5696 100644 --- a/src/lib/methods/include.spec.ts +++ b/src/lib/methods/include.spec.ts @@ -7,7 +7,7 @@ describe("(method) include", () => { it("Creates a proxy from an origin without action", () => { const target = 360; const origin: Exotic.proxy.origin = {}; - const proxy = $.include(origin, target); + const proxy = $.include("", origin, target); expect($.target(proxy)).toBe(target); }); @@ -16,7 +16,7 @@ describe("(method) include", () => { const target = ["example"]; const origin: Exotic.proxy.origin = { ref: reference }; - await $.include(origin, target); + await $.include("", origin, target); expect($.refs.includes(reference)).toBe(true); expect($.useRef(reference)).toBe($.use(target)); @@ -34,7 +34,7 @@ describe("(method) include", () => { use(); }); - await $.include(origin, target); + await $.include("", origin, target); expect($.refs.includes(reference)).toBe(true); expect($.useRef(reference)).toBe($.use(target)); @@ -49,7 +49,7 @@ describe("(method) include", () => { value, proxy, }; - $.include(origin); + $.include("", origin); expect($.target(proxy.test)).toBe(value); }); @@ -61,7 +61,7 @@ describe("(method) include", () => { that: proxy, args: [10], }; - const newProxy = $.include(origin); + const newProxy = $.include("", origin); expect($.target(newProxy)).toBe("test10"); }); @@ -73,7 +73,7 @@ describe("(method) include", () => { proxy, args: [10], }; - const instance = $.include(origin); + const instance = $.include("", origin); expect($.target(instance) instanceof MyClass).toBe(true); }); @@ -85,7 +85,20 @@ describe("(method) include", () => { proxy, key: "test", }; - const proxyFromGet = $.include(origin); + const proxyFromGet = $.include("", origin); expect($.target(proxyFromGet)).toBe(array); }); + + it("Creates a link between an existing proxy and a new proxy", () => { + const proxy = $.use(); + const origin: Exotic.proxy.origin = { + action: "get", + proxy, + key: "test", + }; + const proxyLink = $.encode(proxy); + const newProxy = $.include(proxyLink, origin); + expect($.decode(proxyLink)).toBe(newProxy); + expect(proxy).not.toBe(newProxy); + }); }); diff --git a/src/lib/methods/include.ts b/src/lib/methods/include.ts index 1f17870..66251d8 100644 --- a/src/lib/methods/include.ts +++ b/src/lib/methods/include.ts @@ -4,18 +4,20 @@ import { traps, createProxy, decode, + encode, findProxy, } from "../../utils/index.js"; export default function include( scope: Exotic.Emulator, + encodedProxy: string, origin: Exotic.proxy.origin, target?: any, ): any { const decodedOrigin = decode(scope, origin); const decodedTarget = decode(scope, target); - const targetProxy = findProxy(decodedTarget); - const newTarget = targetProxy ? targetProxy : target; + const proxyAsTarget = findProxy(decodedTarget); + const newTarget = proxyAsTarget ? proxyAsTarget : target; const { action, proxy, key, value, that, args, ref } = decodedOrigin; if (ref) { @@ -39,24 +41,37 @@ export default function include( } const originData = map.proxies.get(proxy); + const { links } = map.emulators.get(scope); if (!originData) { return; } const { mock, sandbox } = originData; + let proxyFromTrap: Exotic.Proxy | undefined; switch (action) { case "get": - if (!key) return; - return traps.get(mock, key); + proxyFromTrap = traps.get(mock, key); + break; case "set": - if (!key) return; traps.set(mock, key, value); - return sandbox[key]; + proxyFromTrap = sandbox[key]; + break; case "apply": - return traps.apply(mock, that, args); + proxyFromTrap = traps.apply(mock, that, args); + break; case "construct": - return traps.construct(mock, args); + proxyFromTrap = traps.construct(mock, args); + break; } + + if (proxyFromTrap) { + const localEncodedProxy = encode(proxyFromTrap); + if (localEncodedProxy !== encodedProxy) { + links[encodedProxy] = localEncodedProxy; + } + } + + return proxyFromTrap; } diff --git a/src/types/Exotic.ts b/src/types/Exotic.ts index ca93678..7c8126f 100644 --- a/src/types/Exotic.ts +++ b/src/types/Exotic.ts @@ -8,7 +8,7 @@ declare namespace Exotic { interface Emulator extends EventEmitter { use(value?: any): Proxy; useRef(ref: key, value?: any): Proxy; - include(origin: proxy.origin, target?: any): any; + include(encodedProxy: string, origin: proxy.origin, target?: any): any; target(value?: any): any; parent(value?: traceable): undefined | Proxy; values(value?: traceable): Proxy[]; @@ -27,12 +27,13 @@ declare namespace Exotic { namespace emulator { interface options { - traceErrors: boolean; + traceErrors?: boolean; } interface data { options: options; refs: Record; + links: Record; counter: number; proxySet: Set; } diff --git a/src/utils/createProxy.ts b/src/utils/createProxy.ts index 7c60528..73f7c33 100644 --- a/src/utils/createProxy.ts +++ b/src/utils/createProxy.ts @@ -5,7 +5,6 @@ import isTraceable from "./isTraceable.js"; import mockPrototype from "./mockPrototype.js"; import traps from "./traps/index.js"; import encode from "./encode.js"; -//import decode from "./decode.js"; const createProxy = ( scope: Exotic.Emulator, @@ -14,24 +13,24 @@ const createProxy = ( ): Exotic.Proxy => { const data: Exotic.emulator.data = map.emulators.get(scope); const { refs, options, proxySet } = data; - //const decodedTarget = decode(scope, target); - const usableProxy = findProxy(target); const error = options.traceErrors ? new Error() : undefined; - // console.log("[createProxy]", data.counter + 1); - - scope.emit("proxy", encode(origin), encode(target), error); + const usableProxy = findProxy(target); + const encodedOrigin = encode(origin); + const encodedTarget = encode(target); if (usableProxy) { // proxy already exists - if ( - origin.action === "apply" || - origin.action === "construct" || - origin.action === "get" || - origin.action === "set" - ) { + if (origin.action) { data.counter++; } + scope.emit( + "proxy", + encode(usableProxy), + encodedOrigin, + encodedTarget, + error, + ); return usableProxy; } @@ -43,6 +42,13 @@ const createProxy = ( // proxy reference exists const proxyRef = refs[reference]; if (proxyRef) { + scope.emit( + "proxy", + encode(proxyRef), + encodedOrigin, + encodedTarget, + error, + ); return proxyRef; } } @@ -91,6 +97,7 @@ const createProxy = ( map.targets.set(target, proxy); } + scope.emit("proxy", encode(proxy), encodedOrigin, encodedTarget, error); return proxy; }; diff --git a/src/utils/decode.ts b/src/utils/decode.ts index 5afc020..5138d54 100644 --- a/src/utils/decode.ts +++ b/src/utils/decode.ts @@ -3,6 +3,7 @@ import findProxy from "./findProxy.js"; import findProxyById from "./findProxyById.js"; import isPayload from "./isPayload.js"; import isTraceable from "./isTraceable.js"; +import map from "./map.js"; export default function decode( scope: Exotic.Emulator, @@ -12,13 +13,15 @@ export default function decode( const traceable = isTraceable(value); const proxy = findProxy(value); const payload = isPayload(value); + const { links } = map.emulators.get(scope); if (proxy) { return proxy; } if (payload) { - return findProxyById(scope, parseInt(value.substring(1))); + const link = links[value] || value; + return findProxyById(scope, parseInt(link.substring(1))); } if (traceable) { diff --git a/src/utils/revokeProxy.ts b/src/utils/revokeProxy.ts index 3649c77..31ee78f 100644 --- a/src/utils/revokeProxy.ts +++ b/src/utils/revokeProxy.ts @@ -11,14 +11,14 @@ const revokeProxy = (value: Exotic.traceable): boolean => { } const proxyData = map.proxies.get(proxy); - const { mock, revoke, target, origin, revoked, key, scope } = proxyData; + const { id, mock, revoke, target, origin, revoked, key, scope } = proxyData; if (revoked) { return true; } const data = map.emulators.get(scope); - const { refs, proxySet } = data; + const { refs, proxySet, links } = data; const validKey = key !== undefined; if (validKey) { @@ -48,6 +48,7 @@ const revokeProxy = (value: Exotic.traceable): boolean => { map.mocks.delete(mock); map.targets.delete(target); proxySet.delete(proxy); + delete links[`⁠${id}`]; // keep in proxies map // prevents proxy out of revoked proxy (throws) @@ -69,6 +70,7 @@ const revokeProxy = (value: Exotic.traceable): boolean => { // clean internal state Object.assign(data, { refs: Object.create(null), + links: Object.create(null), counter: 0, } as Exotic.emulator.data); } diff --git a/src/utils/traps/apply.ts b/src/utils/traps/apply.ts index acb5805..ab30119 100644 --- a/src/utils/traps/apply.ts +++ b/src/utils/traps/apply.ts @@ -3,7 +3,7 @@ import createProxy from "../createProxy.js"; import findProxy from "../findProxy.js"; import map from "../map.js"; -const apply = (mock: Exotic.Mock, that?: any, args?: any[]): any => { +const apply = (mock: Exotic.Mock, that?: any, args?: any[]): Exotic.Proxy => { const proxy = findProxy(mock); const { scope, target } = map.proxies.get(proxy); @@ -22,17 +22,8 @@ const apply = (mock: Exotic.Mock, that?: any, args?: any[]): any => { scope.target(that), origin.args.map((arg) => scope.target(arg)), ); - // console.log( - // scope.target(target), - // scope.target(that), - // args, - // origin.args, - // origin.args.map((arg) => scope.target(arg)), - // ); } - //console.log("[trap_apply]", args, scope.encode(origin), value); - return createProxy(scope, origin, value); }; diff --git a/src/utils/traps/construct.ts b/src/utils/traps/construct.ts index 1014253..da869dc 100644 --- a/src/utils/traps/construct.ts +++ b/src/utils/traps/construct.ts @@ -3,7 +3,7 @@ import createProxy from "../createProxy.js"; import findProxy from "../findProxy.js"; import map from "../map.js"; -const construct = (mock: Exotic.Mock, args: any[]): object => { +const construct = (mock: Exotic.Mock, args: any[]): Exotic.Proxy => { const proxy = findProxy(mock); const { scope, target } = map.proxies.get(proxy); @@ -18,7 +18,7 @@ const construct = (mock: Exotic.Mock, args: any[]): object => { if (typeof target === "function") { value = Reflect.construct( scope.target(target), - args.map((arg) => scope.target(arg)), + origin.args.map((arg) => scope.target(arg)), ); } diff --git a/src/utils/traps/get.ts b/src/utils/traps/get.ts index 1ace0ac..c1d544b 100644 --- a/src/utils/traps/get.ts +++ b/src/utils/traps/get.ts @@ -3,7 +3,7 @@ import createProxy from "../createProxy.js"; import findProxy from "../findProxy.js"; import map from "../map.js"; -const get = (mock: Exotic.Mock, key: any): any => { +const get = (mock: Exotic.Mock, key: any): Exotic.Proxy => { if (key === Symbol.iterator) { return mock[key]; }