Skip to content

Commit 80e2cdd

Browse files
committed
simplified known types + token handling
1 parent 0eaa7fd commit 80e2cdd

File tree

3 files changed

+116
-62
lines changed

3 files changed

+116
-62
lines changed

esm/index.js

+29-32
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
import * as handlerTraps from 'proxy-target/traps';
2-
import * as handlerTypes from 'proxy-target/types';
2+
3+
import { ARRAY, FUNCTION, NULL, OBJECT, UNDEFINED } from 'proxy-target/types';
34
import { bound } from 'proxy-target';
45
import { create, drop } from 'gc-hook';
56

6-
const { ARRAY, FUNCTION, NULL, OBJECT } = handlerTypes;
77
const { Object, Proxy, Reflect } = globalThis;
88

99
const { isArray } = Array;
1010
const { create: extend, entries, values } = Object;
1111

1212
const traps = new Set([...values(handlerTraps)]);
13-
const types = new Set([...values(handlerTypes)]);
1413
const typesOf = new WeakMap;
1514

1615
const extendHandler = (handler, type, value) => {
@@ -20,7 +19,18 @@ const extendHandler = (handler, type, value) => {
2019
return extend(handler, descriptors);
2120
};
2221

23-
const proxy = ($, target, handler, token = false) => {
22+
const proxy = ($, target, handler, token = $) => {
23+
if (token === $) {
24+
switch (typeof $) {
25+
case OBJECT:
26+
case FUNCTION:
27+
case UNDEFINED: break;
28+
default: {
29+
token = false;
30+
if (target === $) target = Object($);
31+
}
32+
}
33+
}
2434
const p = new Proxy(target, handler);
2535
const { destruct } = handler;
2636
return destruct ? create($, destruct, { token, return: p }) : p;
@@ -58,26 +68,12 @@ export const proxyOf = namespace => {
5868
break;
5969
}
6070
default: {
61-
if (types.has(type)) {
62-
const handler = extendHandler(traps, type, method => ({
63-
value($, ..._) {
64-
return method.call(this, $.valueOf(), ..._);
65-
}
66-
}));
67-
proxies[type] = ($, ..._) => {
68-
const p = proxy($, Object($), handler, ..._);
69-
typesOf.set(p, type);
70-
return p;
71-
};
72-
}
73-
else {
74-
const handler = extendHandler(traps, type, value => ({ value }));
75-
proxies[type] = ($, token = $) => {
76-
const p = proxy($, $, handler, token);
77-
typesOf.set(p, type);
78-
return p;
79-
};
80-
}
71+
const handler = extendHandler(traps, type, value => ({ value }));
72+
proxies[type] = ($, ..._) => {
73+
const p = proxy($, $, handler, ..._);
74+
typesOf.set(p, type);
75+
return p;
76+
};
8177
break;
8278
}
8379
}
@@ -86,12 +82,13 @@ export const proxyOf = namespace => {
8682
};
8783

8884
export const typeOf = value => {
89-
let type = typeof value;
90-
if (type === OBJECT) {
91-
type = value === null ?
92-
NULL :
93-
(isArray(value) ? ARRAY : (typesOf.get(value) || OBJECT))
94-
;
95-
}
96-
return type;
85+
const type = typeof value;
86+
return type === OBJECT ?
87+
(value ?
88+
(typesOf.get(value) || (
89+
isArray(value) ? ARRAY : OBJECT
90+
)) :
91+
NULL
92+
) :
93+
type;
9794
};

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"build": "npm run cjs && npm run test",
88
"cjs": "ascjs esm cjs",
99
"coveralls": "c8 report --reporter=text-lcov | coveralls",
10-
"test": "c8 node test/index.js"
10+
"test": "c8 node --expose-gc test/index.js"
1111
},
1212
"keywords": [],
1313
"author": "Andrea Giammarchi",

test/index.js

+86-29
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
11
import { typeOf, proxyOf } from '../esm/index.js';
22

3+
const assert = (current, expected, message = `expected ${expected} - got ${current}`) => {
4+
if (!Object.is(current, expected))
5+
throw new Error(message);
6+
};
7+
38
// 🦄 typeOf coverage related
49
let proxied = proxyOf({
510
// native cases
611
array: {},
712
function: {},
813
object: {},
914

10-
// extra primitives
15+
// custom primitives
1116
bigint: {
12-
get(target, key) {
13-
const value = target[key];
14-
return typeof value === 'function' ?
15-
value.bind(target) : value;
17+
get(target, key, ..._) {
18+
return key === Symbol.toPrimitive ?
19+
() => target.valueOf() :
20+
Reflect.get(target, key, ..._);
1621
},
17-
getPrototypeOf: () => BigInt.prototype,
1822
},
1923
boolean: {},
2024
null: {},
@@ -28,31 +32,84 @@ let proxied = proxyOf({
2832
});
2933

3034
// typeOf native cases
31-
console.assert(typeOf([]) === 'array');
32-
console.assert(typeOf(proxied.array(0)) === 'array');
33-
console.assert(typeOf(()=>{}) === 'function');
34-
console.assert(typeOf(proxied.function(0)) === 'function');
35-
console.assert(typeOf({}) === 'object');
36-
console.assert(typeOf(proxied.object(0)) === 'object');
35+
assert(typeOf([]), 'array');
36+
assert(typeOf(proxied.array(0)), 'array');
37+
assert(typeOf(()=>{}), 'function');
38+
assert(typeOf(proxied.function(0)), 'function');
39+
assert(typeOf({}), 'object');
40+
assert(typeOf(proxied.object(0)), 'object');
3741

3842
// typeOf extra primitives
39-
console.assert(typeOf(1n) === 'bigint');
40-
console.assert(typeOf(proxied.bigint(0)) === 'bigint');
41-
console.assert(typeOf(false) === 'boolean');
42-
console.assert(typeOf(proxied.boolean(0)) === 'boolean');
43-
console.assert(typeOf(null) === 'null');
44-
console.assert(typeOf(proxied.null(0)) === 'null');
45-
console.assert(typeOf(1) === 'number');
46-
console.assert(typeOf(proxied.number(0)) === 'number');
47-
console.assert(typeOf('') === 'string');
48-
console.assert(typeOf(proxied.string(0)) === 'string');
49-
console.assert(typeOf(Symbol()) === 'symbol');
50-
console.assert(typeOf(proxied.symbol(0)) === 'symbol');
51-
console.assert(typeOf() === 'undefined');
52-
console.assert(typeOf(proxied.undefined({})) === 'undefined');
43+
assert(typeOf(1n), 'bigint');
44+
assert(typeOf(proxied.bigint(0)), 'bigint');
45+
assert(typeOf(false), 'boolean');
46+
assert(typeOf(proxied.boolean(0)), 'boolean');
47+
assert(typeOf(null), 'null');
48+
assert(typeOf(proxied.null(0)), 'null');
49+
assert(typeOf(1), 'number');
50+
assert(typeOf(proxied.number(0)), 'number');
51+
assert(typeOf(''), 'string');
52+
assert(typeOf(proxied.string(0)), 'string');
53+
assert(typeOf(Symbol()), 'symbol');
54+
assert(typeOf(proxied.symbol(0)), 'symbol');
55+
assert(typeOf(), 'undefined');
56+
assert(typeOf(proxied.undefined(0)), 'undefined');
5357

5458
// typeOf custom direct/defined
55-
console.assert(typeOf(proxied.direct({})) === 'direct');
59+
assert(typeOf(proxied.direct({})), 'direct');
60+
61+
assert(proxied.bigint(2n) == 2n, true, 'bigint');
62+
assert(proxied.bigint(2n) instanceof BigInt, true, 'bigint instanceof');
63+
64+
// 🦄 proxyOf coverage related
65+
assert(proxied.array([1, 2, 3]).length, 3);
66+
assert(proxied.direct([1, 2, 3]).length, 3);
67+
assert(proxied.object({a: 1}).a, 1);
68+
assert(proxied.direct({a: 1}).a, 1);
69+
assert(proxied.function(() => 1)(), 1);
70+
assert(proxied.direct(() => 1)(), 1);
71+
72+
let i = 0;
73+
74+
const gcdo = Object(1);
75+
const gcdd = {b: 2};
76+
77+
proxied = proxyOf({
78+
object: {
79+
destruct(ref) {
80+
assert(ref, gcdo.valueOf());
81+
i++;
82+
}
83+
},
84+
direct: {
85+
destruct(ref) {
86+
assert(ref, gcdd);
87+
i++;
88+
}
89+
},
90+
});
91+
92+
93+
let pgcdo = proxied.object(gcdo.valueOf(), gcdo);
94+
let pgcdd = proxied.direct(gcdd);
5695

57-
console.assert(proxied.bigint(2n) == 2n);
58-
console.assert(proxied.bigint(2n) instanceof BigInt);
96+
setTimeout(() => {
97+
pgcdo = pgcdd = null;
98+
gc();
99+
setTimeout(() => {
100+
gc();
101+
assert(i, 2);
102+
pgcdo = proxied.object(gcdo.valueOf(), gcdo);
103+
pgcdd = proxied.direct(gcdd);
104+
setTimeout(() => {
105+
proxied.free(gcdo);
106+
proxied.free(gcdd);
107+
gc();
108+
setTimeout(() => {
109+
gc();
110+
assert(i, 2);
111+
console.log('OK');
112+
}, 100);
113+
}, 100);
114+
});
115+
}, 100);

0 commit comments

Comments
 (0)