unreflect 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -10
- package/dist/index.d.mts +3 -0
- package/dist/index.mjs +99 -23
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@ import { ReflectionClass } from "unreflect";
|
|
|
22
22
|
|
|
23
23
|
class User {
|
|
24
24
|
#name = "John";
|
|
25
|
-
|
|
25
|
+
email = "john@example.com";
|
|
26
26
|
|
|
27
27
|
getName() {
|
|
28
28
|
return this.#name;
|
|
@@ -35,22 +35,27 @@ const ref = new ReflectionClass(user);
|
|
|
35
35
|
// Get class name
|
|
36
36
|
ref.getClassName(); // "User"
|
|
37
37
|
|
|
38
|
-
// Get/set
|
|
39
|
-
await ref.getPropertyValue("name"); // "John"
|
|
38
|
+
// Get/set public properties
|
|
40
39
|
await ref.getPropertyValue("email"); // "john@example.com"
|
|
40
|
+
ref.setProperty("email", "jane@example.com");
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
// Get/set private properties (use # prefix)
|
|
43
|
+
await ref.getPropertyValue("#name"); // "John"
|
|
44
|
+
ref.setProperty("#name", "Jane");
|
|
43
45
|
user.getName(); // "Jane"
|
|
44
46
|
|
|
45
47
|
// Get property metadata
|
|
46
|
-
await ref.getProperty("name");
|
|
47
|
-
// { name: "name", visibility: "private", value: "Jane" }
|
|
48
|
+
await ref.getProperty("#name");
|
|
49
|
+
// { name: "#name", visibility: "private", value: "Jane" }
|
|
50
|
+
|
|
51
|
+
await ref.getProperty("email");
|
|
52
|
+
// { name: "email", visibility: "public", value: "jane@example.com" }
|
|
48
53
|
|
|
49
54
|
// List all properties
|
|
50
55
|
await ref.getProperties();
|
|
51
56
|
// [
|
|
52
|
-
// { name: "email", visibility: "public", value: "
|
|
53
|
-
// { name: "name", visibility: "private" }
|
|
57
|
+
// { name: "email", visibility: "public", value: "jane@example.com" },
|
|
58
|
+
// { name: "#name", visibility: "private" }
|
|
54
59
|
// ]
|
|
55
60
|
|
|
56
61
|
// List all methods (including private)
|
|
@@ -60,7 +65,8 @@ await ref.getMethods();
|
|
|
60
65
|
// ]
|
|
61
66
|
|
|
62
67
|
// Check existence
|
|
63
|
-
await ref.hasProperty("name"); // true
|
|
68
|
+
await ref.hasProperty("#name"); // true
|
|
69
|
+
await ref.hasProperty("email"); // true
|
|
64
70
|
await ref.hasMethod("getName"); // true
|
|
65
71
|
```
|
|
66
72
|
|
|
@@ -69,7 +75,7 @@ await ref.hasMethod("getName"); // true
|
|
|
69
75
|
| Method | Description |
|
|
70
76
|
| -------------------------- | --------------------------------------------------- |
|
|
71
77
|
| `getClassName()` | Returns the class name |
|
|
72
|
-
| `setProperty(name, value)` | Sets a property value (
|
|
78
|
+
| `setProperty(name, value)` | Sets a property value (use `#` prefix for private) |
|
|
73
79
|
| `getProperty(name)` | Returns property metadata with visibility and value |
|
|
74
80
|
| `getPropertyValue(name)` | Returns just the property value |
|
|
75
81
|
| `getProperties()` | Returns all properties with visibility |
|
package/dist/index.d.mts
CHANGED
|
@@ -14,6 +14,9 @@ declare class ReflectionClass {
|
|
|
14
14
|
private obj;
|
|
15
15
|
private values;
|
|
16
16
|
constructor(obj: any);
|
|
17
|
+
private isPrivateName;
|
|
18
|
+
private getBaseName;
|
|
19
|
+
private stripPrivateInitializers;
|
|
17
20
|
setProperty(name: string, value: any): void;
|
|
18
21
|
getProperty(name: string): Promise<ReflectionProperty | undefined>;
|
|
19
22
|
getPropertyValue(name: string): Promise<any>;
|
package/dist/index.mjs
CHANGED
|
@@ -8,19 +8,89 @@ var ReflectionClass = class {
|
|
|
8
8
|
constructor(obj) {
|
|
9
9
|
this.obj = obj;
|
|
10
10
|
}
|
|
11
|
+
isPrivateName(name) {
|
|
12
|
+
return name.startsWith("#");
|
|
13
|
+
}
|
|
14
|
+
getBaseName(name) {
|
|
15
|
+
return name.startsWith("#") ? name.slice(1) : name;
|
|
16
|
+
}
|
|
17
|
+
stripPrivateInitializers(source) {
|
|
18
|
+
const lines = source.split("\n");
|
|
19
|
+
const result = [];
|
|
20
|
+
let skipUntilBalanced = false;
|
|
21
|
+
let braceDepth = 0;
|
|
22
|
+
let bracketDepth = 0;
|
|
23
|
+
let parenDepth = 0;
|
|
24
|
+
for (const line of lines) {
|
|
25
|
+
const isMethod = /^\s*#\w+\s*\(/.test(line);
|
|
26
|
+
const fieldMatch = line.match(/^(\s*)(#\w+)/);
|
|
27
|
+
if (!isMethod && fieldMatch?.[1] !== void 0 && fieldMatch[2] && !skipUntilBalanced) {
|
|
28
|
+
result.push(fieldMatch[1] + fieldMatch[2]);
|
|
29
|
+
if (line.includes("=")) {
|
|
30
|
+
for (const ch of line) switch (ch) {
|
|
31
|
+
case "{":
|
|
32
|
+
braceDepth++;
|
|
33
|
+
break;
|
|
34
|
+
case "}":
|
|
35
|
+
braceDepth--;
|
|
36
|
+
break;
|
|
37
|
+
case "[":
|
|
38
|
+
bracketDepth++;
|
|
39
|
+
break;
|
|
40
|
+
case "]":
|
|
41
|
+
bracketDepth--;
|
|
42
|
+
break;
|
|
43
|
+
case "(":
|
|
44
|
+
parenDepth++;
|
|
45
|
+
break;
|
|
46
|
+
case ")":
|
|
47
|
+
parenDepth--;
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
if (braceDepth > 0 || bracketDepth > 0 || parenDepth > 0) skipUntilBalanced = true;
|
|
51
|
+
}
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (skipUntilBalanced) {
|
|
55
|
+
for (const ch of line) switch (ch) {
|
|
56
|
+
case "{":
|
|
57
|
+
braceDepth++;
|
|
58
|
+
break;
|
|
59
|
+
case "}":
|
|
60
|
+
braceDepth--;
|
|
61
|
+
break;
|
|
62
|
+
case "[":
|
|
63
|
+
bracketDepth++;
|
|
64
|
+
break;
|
|
65
|
+
case "]":
|
|
66
|
+
bracketDepth--;
|
|
67
|
+
break;
|
|
68
|
+
case "(":
|
|
69
|
+
parenDepth++;
|
|
70
|
+
break;
|
|
71
|
+
case ")":
|
|
72
|
+
parenDepth--;
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
if (braceDepth === 0 && bracketDepth === 0 && parenDepth === 0) skipUntilBalanced = false;
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
result.push(line);
|
|
79
|
+
}
|
|
80
|
+
return result.join("\n");
|
|
81
|
+
}
|
|
11
82
|
setProperty(name, value) {
|
|
12
83
|
const obj = this.obj;
|
|
13
|
-
|
|
14
|
-
|
|
84
|
+
const isPrivate = this.isPrivateName(name);
|
|
85
|
+
const baseName = this.getBaseName(name);
|
|
86
|
+
if (!isPrivate) {
|
|
87
|
+
obj[baseName] = value;
|
|
15
88
|
return;
|
|
16
89
|
}
|
|
17
90
|
const proto = Object.getPrototypeOf(obj);
|
|
18
91
|
const classSource = proto.constructor.toString();
|
|
19
|
-
if (!classSource.includes(`#${
|
|
20
|
-
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
const modifiedSource = classSource.replace(/#(\w+)\s*=\s*[^;]+;/g, "#$1;").replace(/^(class\s+\w+)\s*\{/, `$1 { static __reflectionSet__(obj, val) { obj.#${name} = val; } static __reflectionGet__(obj) { return obj.#${name}; }`);
|
|
92
|
+
if (!classSource.includes(`#${baseName}`)) return;
|
|
93
|
+
const modifiedSource = this.stripPrivateInitializers(classSource).replace(/^(class\s+\w+)\s*\{/, `$1 { static __reflectionSet__(obj, val) { obj.#${baseName} = val; } static __reflectionGet__(obj) { return obj.#${baseName}; }`);
|
|
24
94
|
const ModifiedClass = vm.runInThisContext(`(${modifiedSource})`);
|
|
25
95
|
Object.setPrototypeOf(obj, ModifiedClass.prototype);
|
|
26
96
|
const originalProps = Object.getOwnPropertyDescriptors(obj);
|
|
@@ -33,7 +103,7 @@ var ReflectionClass = class {
|
|
|
33
103
|
});
|
|
34
104
|
Object.setPrototypeOf(obj, proto);
|
|
35
105
|
const methodNames = Object.getOwnPropertyNames(proto).filter((n) => n !== "constructor" && typeof proto[n] === "function");
|
|
36
|
-
for (const methodName of methodNames) if (proto[methodName].toString().includes(`#${
|
|
106
|
+
for (const methodName of methodNames) if (proto[methodName].toString().includes(`#${baseName}`)) {
|
|
37
107
|
const boundMethod = ModifiedClass.prototype[methodName].bind(freshInstance);
|
|
38
108
|
Object.defineProperty(obj, methodName, {
|
|
39
109
|
value: boundMethod,
|
|
@@ -44,10 +114,21 @@ var ReflectionClass = class {
|
|
|
44
114
|
}
|
|
45
115
|
async getProperty(name) {
|
|
46
116
|
const obj = this.obj;
|
|
47
|
-
|
|
117
|
+
const isPrivate = this.isPrivateName(name);
|
|
118
|
+
const baseName = this.getBaseName(name);
|
|
119
|
+
if (!isPrivate) {
|
|
120
|
+
if (Object.prototype.hasOwnProperty.call(obj, baseName)) return {
|
|
121
|
+
name: baseName,
|
|
122
|
+
visibility: "public",
|
|
123
|
+
value: obj[baseName]
|
|
124
|
+
};
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const cached = this.values.get(name);
|
|
128
|
+
if (cached) return {
|
|
48
129
|
name,
|
|
49
|
-
visibility: "
|
|
50
|
-
value:
|
|
130
|
+
visibility: "private",
|
|
131
|
+
value: cached.ModifiedClass.__reflectionGet__(cached.freshInstance)
|
|
51
132
|
};
|
|
52
133
|
const id = `__ref_${Date.now()}_${Math.random().toString(36).slice(2)}__`;
|
|
53
134
|
globalThis[id] = obj;
|
|
@@ -59,7 +140,7 @@ var ReflectionClass = class {
|
|
|
59
140
|
const privateProp = (await session.post("Runtime.getProperties", {
|
|
60
141
|
objectId: result.objectId,
|
|
61
142
|
ownProperties: true
|
|
62
|
-
})).privateProperties?.find((p) => p.name === `#${
|
|
143
|
+
})).privateProperties?.find((p) => p.name === `#${baseName}`);
|
|
63
144
|
if (!privateProp) return;
|
|
64
145
|
let value;
|
|
65
146
|
if (privateProp.value.type === "object" && privateProp.value.objectId) {
|
|
@@ -82,8 +163,6 @@ var ReflectionClass = class {
|
|
|
82
163
|
}
|
|
83
164
|
}
|
|
84
165
|
async getPropertyValue(name) {
|
|
85
|
-
const cached = this.values.get(name);
|
|
86
|
-
if (cached) return cached.ModifiedClass.__reflectionGet__(cached.freshInstance);
|
|
87
166
|
return (await this.getProperty(name))?.value;
|
|
88
167
|
}
|
|
89
168
|
getClassName() {
|
|
@@ -112,13 +191,10 @@ var ReflectionClass = class {
|
|
|
112
191
|
objectId: result.objectId,
|
|
113
192
|
ownProperties: true
|
|
114
193
|
});
|
|
115
|
-
if (props.privateProperties) for (const prop of props.privateProperties) {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
visibility: "private"
|
|
120
|
-
});
|
|
121
|
-
}
|
|
194
|
+
if (props.privateProperties) for (const prop of props.privateProperties) properties.push({
|
|
195
|
+
name: prop.name,
|
|
196
|
+
visibility: "private"
|
|
197
|
+
});
|
|
122
198
|
} finally {
|
|
123
199
|
delete globalThis[id];
|
|
124
200
|
session.disconnect();
|
|
@@ -163,7 +239,7 @@ var ReflectionClass = class {
|
|
|
163
239
|
ownProperties: true
|
|
164
240
|
});
|
|
165
241
|
for (const prop of methodsProps.result || []) {
|
|
166
|
-
const match = (prop.value?.description || "").match(
|
|
242
|
+
const match = (prop.value?.description || "").match(/^(#\w+)\s*\(/);
|
|
167
243
|
if (match) methods.push({
|
|
168
244
|
name: match[1],
|
|
169
245
|
visibility: "private",
|
|
@@ -178,7 +254,7 @@ var ReflectionClass = class {
|
|
|
178
254
|
return methods;
|
|
179
255
|
}
|
|
180
256
|
async hasProperty(name) {
|
|
181
|
-
return
|
|
257
|
+
return await this.getProperty(name) !== void 0;
|
|
182
258
|
}
|
|
183
259
|
async hasMethod(name) {
|
|
184
260
|
return (await this.getMethods()).some((m) => m.name === name);
|