unreflect 0.0.1 → 0.0.2

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 CHANGED
@@ -22,7 +22,7 @@ import { ReflectionClass } from "unreflect";
22
22
 
23
23
  class User {
24
24
  #name = "John";
25
- public email = "john@example.com";
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 property values (public and private)
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
- ref.setProperty("name", "Jane");
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: "john@example.com" },
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 (public or private) |
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,8 @@ declare class ReflectionClass {
14
14
  private obj;
15
15
  private values;
16
16
  constructor(obj: any);
17
+ private isPrivateName;
18
+ private getBaseName;
17
19
  setProperty(name: string, value: any): void;
18
20
  getProperty(name: string): Promise<ReflectionProperty | undefined>;
19
21
  getPropertyValue(name: string): Promise<any>;
package/dist/index.mjs CHANGED
@@ -8,19 +8,24 @@ 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
+ }
11
17
  setProperty(name, value) {
12
18
  const obj = this.obj;
13
- if (Object.prototype.hasOwnProperty.call(obj, name)) {
14
- obj[name] = value;
19
+ const isPrivate = this.isPrivateName(name);
20
+ const baseName = this.getBaseName(name);
21
+ if (!isPrivate) {
22
+ obj[baseName] = value;
15
23
  return;
16
24
  }
17
25
  const proto = Object.getPrototypeOf(obj);
18
26
  const classSource = proto.constructor.toString();
19
- if (!classSource.includes(`#${name}`)) {
20
- obj[name] = value;
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}; }`);
27
+ if (!classSource.includes(`#${baseName}`)) return;
28
+ const modifiedSource = classSource.replace(/#(\w+)\s*=\s*[^;]+;/g, "#$1;").replace(/^(class\s+\w+)\s*\{/, `$1 { static __reflectionSet__(obj, val) { obj.#${baseName} = val; } static __reflectionGet__(obj) { return obj.#${baseName}; }`);
24
29
  const ModifiedClass = vm.runInThisContext(`(${modifiedSource})`);
25
30
  Object.setPrototypeOf(obj, ModifiedClass.prototype);
26
31
  const originalProps = Object.getOwnPropertyDescriptors(obj);
@@ -33,7 +38,7 @@ var ReflectionClass = class {
33
38
  });
34
39
  Object.setPrototypeOf(obj, proto);
35
40
  const methodNames = Object.getOwnPropertyNames(proto).filter((n) => n !== "constructor" && typeof proto[n] === "function");
36
- for (const methodName of methodNames) if (proto[methodName].toString().includes(`#${name}`)) {
41
+ for (const methodName of methodNames) if (proto[methodName].toString().includes(`#${baseName}`)) {
37
42
  const boundMethod = ModifiedClass.prototype[methodName].bind(freshInstance);
38
43
  Object.defineProperty(obj, methodName, {
39
44
  value: boundMethod,
@@ -44,10 +49,21 @@ var ReflectionClass = class {
44
49
  }
45
50
  async getProperty(name) {
46
51
  const obj = this.obj;
47
- if (Object.prototype.hasOwnProperty.call(obj, name)) return {
52
+ const isPrivate = this.isPrivateName(name);
53
+ const baseName = this.getBaseName(name);
54
+ if (!isPrivate) {
55
+ if (Object.prototype.hasOwnProperty.call(obj, baseName)) return {
56
+ name: baseName,
57
+ visibility: "public",
58
+ value: obj[baseName]
59
+ };
60
+ return;
61
+ }
62
+ const cached = this.values.get(name);
63
+ if (cached) return {
48
64
  name,
49
- visibility: "public",
50
- value: obj[name]
65
+ visibility: "private",
66
+ value: cached.ModifiedClass.__reflectionGet__(cached.freshInstance)
51
67
  };
52
68
  const id = `__ref_${Date.now()}_${Math.random().toString(36).slice(2)}__`;
53
69
  globalThis[id] = obj;
@@ -59,7 +75,7 @@ var ReflectionClass = class {
59
75
  const privateProp = (await session.post("Runtime.getProperties", {
60
76
  objectId: result.objectId,
61
77
  ownProperties: true
62
- })).privateProperties?.find((p) => p.name === `#${name}`);
78
+ })).privateProperties?.find((p) => p.name === `#${baseName}`);
63
79
  if (!privateProp) return;
64
80
  let value;
65
81
  if (privateProp.value.type === "object" && privateProp.value.objectId) {
@@ -82,8 +98,6 @@ var ReflectionClass = class {
82
98
  }
83
99
  }
84
100
  async getPropertyValue(name) {
85
- const cached = this.values.get(name);
86
- if (cached) return cached.ModifiedClass.__reflectionGet__(cached.freshInstance);
87
101
  return (await this.getProperty(name))?.value;
88
102
  }
89
103
  getClassName() {
@@ -112,13 +126,10 @@ var ReflectionClass = class {
112
126
  objectId: result.objectId,
113
127
  ownProperties: true
114
128
  });
115
- if (props.privateProperties) for (const prop of props.privateProperties) {
116
- const name = prop.name.replace(/^#/, "");
117
- properties.push({
118
- name,
119
- visibility: "private"
120
- });
121
- }
129
+ if (props.privateProperties) for (const prop of props.privateProperties) properties.push({
130
+ name: prop.name,
131
+ visibility: "private"
132
+ });
122
133
  } finally {
123
134
  delete globalThis[id];
124
135
  session.disconnect();
@@ -163,7 +174,7 @@ var ReflectionClass = class {
163
174
  ownProperties: true
164
175
  });
165
176
  for (const prop of methodsProps.result || []) {
166
- const match = (prop.value?.description || "").match(/^#(\w+)\s*\(/);
177
+ const match = (prop.value?.description || "").match(/^(#\w+)\s*\(/);
167
178
  if (match) methods.push({
168
179
  name: match[1],
169
180
  visibility: "private",
@@ -178,7 +189,7 @@ var ReflectionClass = class {
178
189
  return methods;
179
190
  }
180
191
  async hasProperty(name) {
181
- return (await this.getProperties()).some((p) => p.name === name);
192
+ return await this.getProperty(name) !== void 0;
182
193
  }
183
194
  async hasMethod(name) {
184
195
  return (await this.getMethods()).some((m) => m.name === name);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unreflect",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "Access and modify private class fields and methods in JavaScript",
5
5
  "repository": "KABBOUCHI/unreflect",
6
6
  "license": "MIT",