diff --git a/src/lib/methods/use.ts b/src/lib/methods/use.ts index 683414c..448c6f0 100644 --- a/src/lib/methods/use.ts +++ b/src/lib/methods/use.ts @@ -3,5 +3,5 @@ import { createProxy } from "../../utils/index.js"; export default function use(scope: Exotic.Emulator, value?: any): Exotic.Proxy { // create a proxy by target reference - return createProxy(scope, undefined, value); + return createProxy(scope, {}, value); } diff --git a/src/utils/createProxy.spec.ts b/src/utils/createProxy.spec.ts index c16d983..c96ce9b 100644 --- a/src/utils/createProxy.spec.ts +++ b/src/utils/createProxy.spec.ts @@ -6,7 +6,7 @@ const $ = new Emulator(); describe("(function) createProxy", () => { it("Returns an existing proxy", () => { const proxy = $.use(); - const sameProxy = createProxy($, undefined, proxy); + const sameProxy = createProxy($, {}, proxy); expect(proxy).toBe(sameProxy); }); @@ -40,7 +40,7 @@ describe("(function) createProxy", () => { it("Adds any target value to a proxy", () => { const target = "target"; - const proxy = createProxy($, undefined, target); + const proxy = createProxy($, {}, target); expect($.target(proxy)).toBe(target); }); diff --git a/src/utils/createProxy.ts b/src/utils/createProxy.ts index e707a11..2437f1c 100644 --- a/src/utils/createProxy.ts +++ b/src/utils/createProxy.ts @@ -10,7 +10,7 @@ import findProxyById from "./findProxyById.js"; const createProxy = ( scope: Exotic.Emulator, - origin: Exotic.proxy.origin = {}, + origin: Exotic.proxy.origin, target?: any, ): Exotic.Proxy => { // find proxy by id @@ -27,7 +27,6 @@ const createProxy = ( const error = options.traceErrors ? new Error() : undefined; const link = origin.action === "link" ? origin.key : undefined; const validLink = link !== undefined; - const usableProxy = findProxy(target); const encodedOrigin = encode(origin); const encodedTarget = encode(target); @@ -38,7 +37,7 @@ const createProxy = ( if (proxyRef) { scope.emit( "proxy", - encode(proxyRef), + `⁠${map.proxies.get(proxyRef).id}`, encodedOrigin, encodedTarget, error, @@ -49,13 +48,15 @@ const createProxy = ( // find a proxy that already exists + const usableProxy = findProxy(target); + if (usableProxy) { if (origin.action) { data.counter++; } scope.emit( "proxy", - encode(usableProxy), + `⁠${map.proxies.get(usableProxy).id}`, encodedOrigin, encodedTarget, error, @@ -72,15 +73,6 @@ const createProxy = ( let { proxy, revoke } = Proxy.revocable(mock, traps); - const id = `${++data.counter}`; - const sandbox = Object.create(null); - - const revokeFunction = () => { - revoke && revoke(); - proxy = null; - revoke = null; - }; - if (validLink) { // create unique reference links[link] = proxy; @@ -88,15 +80,19 @@ const createProxy = ( // add information about this proxy const proxyData: Exotic.proxy.data = { - id, + id: `${++data.counter}`, mock, origin, target, - revoke: revokeFunction, scope, - sandbox, key: link, revoked: false, + sandbox: Object.create(null), + revoke() { + revoke && revoke(); + proxy = null; + revoke = null; + }, }; map.mocks.set(mock, proxy); @@ -107,7 +103,7 @@ const createProxy = ( map.targets.set(target, proxy); } - scope.emit("proxy", encode(proxy), encodedOrigin, encodedTarget, error); + scope.emit("proxy", `⁠${proxyData.id}`, encodedOrigin, encodedTarget, error); return proxy; }; diff --git a/src/utils/decode.ts b/src/utils/decode.ts index 418bf4e..c5a7416 100644 --- a/src/utils/decode.ts +++ b/src/utils/decode.ts @@ -11,24 +11,18 @@ export default function decode( value: any, visited: WeakSet = new WeakSet(), ): any { - const traceable = isTraceable(value); const proxy = findProxy(value); - const payload = isPayload(value); - const { links } = map.emulators.get(scope); if (proxy) { return proxy; } - if (payload) { - const link = links[value]; - if (link) { - return link; - } - return findProxyById(scope, value); + if (isPayload(value)) { + const { links } = map.emulators.get(scope); + return links[value] || findProxyById(scope, value); } - if (traceable) { + if (isTraceable(value)) { if (typeof value === "function") { return value; } @@ -42,14 +36,13 @@ export default function decode( const isArray = Array.isArray(value); const copy = isArray ? [] : {}; - const keys = Object.keys(value); if (isArray) { for (let i = 0; i < value.length; i++) { (copy as any[]).push(decode(scope, value[i], visited)); } } else { - for (const key of keys) { + for (const key of Object.keys(value)) { copy[key] = decode(scope, value[key], visited); } } diff --git a/src/utils/encode.ts b/src/utils/encode.ts index 6bb0ec6..7379b53 100644 --- a/src/utils/encode.ts +++ b/src/utils/encode.ts @@ -7,14 +7,13 @@ export default function encode( value: any, visited: WeakSet = new WeakSet(), ): any { - const traceable = isTraceable(value); const proxy = findProxy(value); if (proxy) { return `⁠${map.proxies.get(proxy).id}`; } - if (traceable) { + if (isTraceable(value)) { if (typeof value === "function") { return value; } @@ -28,14 +27,13 @@ export default function encode( const isArray = Array.isArray(value); const copy = isArray ? [] : {}; - const keys = Object.keys(value); if (isArray) { for (let i = 0; i < value.length; i++) { (copy as any[]).push(encode(value[i], visited)); } } else { - for (const key of keys) { + for (const key of Object.keys(value)) { copy[key] = encode(value[key], visited); } } diff --git a/src/utils/isPayload.ts b/src/utils/isPayload.ts index 77bafd3..27ee791 100644 --- a/src/utils/isPayload.ts +++ b/src/utils/isPayload.ts @@ -2,6 +2,5 @@ import constants from "./constants.js"; export default function isPayload(value: any): boolean { if (typeof value !== "string") return false; - if (!constants.IS_PROXY_ID_REGEXP.test(value)) return false; - return true; + return constants.IS_PROXY_ID_REGEXP.test(value); } diff --git a/src/utils/revokeProxy.ts b/src/utils/revokeProxy.ts index 01dc71a..dea46cb 100644 --- a/src/utils/revokeProxy.ts +++ b/src/utils/revokeProxy.ts @@ -1,6 +1,4 @@ import Exotic from "../types/Exotic.js"; -import decode from "./decode.js"; -import encode from "./encode.js"; import findProxy from "./findProxy.js"; import map from "./map.js"; @@ -12,65 +10,58 @@ 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 { links, proxySet } = data; - const validKey = key !== undefined; + const { links, proxySet, options } = data; - if (validKey) { + if (key !== undefined) { // the key is linked to a proxy // delete this key from the links delete links[key]; } - const decodedOrigin = decode(scope, origin) as Exotic.proxy.origin; - - if (decodedOrigin) { - // remove from proxy's parent references - const { action, key, proxy: parentProxy } = decodedOrigin; - if (action === "get" || action === "set") { - // delete from parent proxy and target - if (parentProxy) { - const data = map.proxies.get(parentProxy); - if (data && !data.revoked) { - delete parentProxy[key]; - } - } + // remove from proxy's parent references + const { action, key: property, proxy: parentProxy } = origin; + if (action === "get" || action === "set") { + // delete from parent proxy and target + const parentProxyData = map.proxies.get(parentProxy); + if (!parentProxyData?.revoked) { + delete parentProxy[property]; } } map.mocks.delete(mock); map.targets.delete(target); proxySet.delete(proxy); - delete links[encode(proxy)]; - - // !! keep in proxies map - // prevents proxy out of revoked proxy (throws) - // map.proxies.delete(proxy); + delete links[`⁠${id}`]; revoke(); - Object.assign(proxyData, { + // !! keep in proxies map + // prevent proxy out of revoked proxy error + + map.proxies.set(proxy, { + id, revoked: true, mock: null, - origin: null, revoke: null, sandbox: null, scope: null, - target: null, - } as Exotic.proxy.data); + }); if (proxySet.size === 0) { // clean internal state - Object.assign(data, { + map.emulators.set(scope, { + options, + proxySet, links: Object.create(null), counter: 0, - } as Exotic.emulator.data); + }); } return true; diff --git a/src/utils/traps/apply.ts b/src/utils/traps/apply.ts index ab30119..aca2a32 100644 --- a/src/utils/traps/apply.ts +++ b/src/utils/traps/apply.ts @@ -11,7 +11,7 @@ const apply = (mock: Exotic.Mock, that?: any, args?: any[]): Exotic.Proxy => { action: "apply", proxy, that, - args: args.map((arg) => createProxy(scope, undefined, arg)), + args: args.map((arg) => createProxy(scope, {}, arg)), }; let value: any; diff --git a/src/utils/traps/construct.ts b/src/utils/traps/construct.ts index 9d0b159..fd45cfc 100644 --- a/src/utils/traps/construct.ts +++ b/src/utils/traps/construct.ts @@ -10,7 +10,7 @@ const construct = (mock: Exotic.Mock, args: any[]): Exotic.Proxy => { const origin: Exotic.proxy.origin = { action: "build", proxy, - args: args.map((arg) => createProxy(scope, undefined, arg)), + args: args.map((arg) => createProxy(scope, {}, arg)), }; let value: any;