unreflect 0.0.2 → 0.0.4

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/dist/index.d.mts CHANGED
@@ -16,6 +16,7 @@ declare class ReflectionClass {
16
16
  constructor(obj: any);
17
17
  private isPrivateName;
18
18
  private getBaseName;
19
+ private stripPrivateInitializers;
19
20
  setProperty(name: string, value: any): void;
20
21
  getProperty(name: string): Promise<ReflectionProperty | undefined>;
21
22
  getPropertyValue(name: string): Promise<any>;
package/dist/index.mjs CHANGED
@@ -14,6 +14,93 @@ var ReflectionClass = class {
14
14
  getBaseName(name) {
15
15
  return name.startsWith("#") ? name.slice(1) : name;
16
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
+ let inConstructor = false;
25
+ let constructorBraceDepth = 0;
26
+ for (const line of lines) {
27
+ if (/^\s*constructor\s*\(/.test(line)) {
28
+ inConstructor = true;
29
+ constructorBraceDepth = 0;
30
+ for (const ch of line) {
31
+ if (ch === "{") constructorBraceDepth++;
32
+ if (ch === "}") constructorBraceDepth--;
33
+ }
34
+ result.push(line.replace(/\{.*$/, "{}"));
35
+ if (constructorBraceDepth > 0) continue;
36
+ inConstructor = false;
37
+ continue;
38
+ }
39
+ if (inConstructor) {
40
+ for (const ch of line) {
41
+ if (ch === "{") constructorBraceDepth++;
42
+ if (ch === "}") constructorBraceDepth--;
43
+ }
44
+ if (constructorBraceDepth === 0) inConstructor = false;
45
+ continue;
46
+ }
47
+ const isMethod = /^\s*#\w+\s*\(/.test(line);
48
+ const fieldMatch = line.match(/^(\s*)(#\w+)/);
49
+ if (!isMethod && fieldMatch?.[1] !== void 0 && fieldMatch[2] && !skipUntilBalanced) {
50
+ result.push(fieldMatch[1] + fieldMatch[2]);
51
+ if (line.includes("=")) {
52
+ for (const ch of line) switch (ch) {
53
+ case "{":
54
+ braceDepth++;
55
+ break;
56
+ case "}":
57
+ braceDepth--;
58
+ break;
59
+ case "[":
60
+ bracketDepth++;
61
+ break;
62
+ case "]":
63
+ bracketDepth--;
64
+ break;
65
+ case "(":
66
+ parenDepth++;
67
+ break;
68
+ case ")":
69
+ parenDepth--;
70
+ break;
71
+ }
72
+ if (braceDepth > 0 || bracketDepth > 0 || parenDepth > 0) skipUntilBalanced = true;
73
+ }
74
+ continue;
75
+ }
76
+ if (skipUntilBalanced) {
77
+ for (const ch of line) switch (ch) {
78
+ case "{":
79
+ braceDepth++;
80
+ break;
81
+ case "}":
82
+ braceDepth--;
83
+ break;
84
+ case "[":
85
+ bracketDepth++;
86
+ break;
87
+ case "]":
88
+ bracketDepth--;
89
+ break;
90
+ case "(":
91
+ parenDepth++;
92
+ break;
93
+ case ")":
94
+ parenDepth--;
95
+ break;
96
+ }
97
+ if (braceDepth === 0 && bracketDepth === 0 && parenDepth === 0) skipUntilBalanced = false;
98
+ continue;
99
+ }
100
+ result.push(line);
101
+ }
102
+ return result.join("\n");
103
+ }
17
104
  setProperty(name, value) {
18
105
  const obj = this.obj;
19
106
  const isPrivate = this.isPrivateName(name);
@@ -25,7 +112,7 @@ var ReflectionClass = class {
25
112
  const proto = Object.getPrototypeOf(obj);
26
113
  const classSource = proto.constructor.toString();
27
114
  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}; }`);
115
+ const modifiedSource = this.stripPrivateInitializers(classSource).replace(/^(class(?:\s+\w+)?)\s*\{/, `$1 { static __reflectionSet__(obj, val) { obj.#${baseName} = val; } static __reflectionGet__(obj) { return obj.#${baseName}; }`);
29
116
  const ModifiedClass = vm.runInThisContext(`(${modifiedSource})`);
30
117
  Object.setPrototypeOf(obj, ModifiedClass.prototype);
31
118
  const originalProps = Object.getOwnPropertyDescriptors(obj);
@@ -37,14 +124,35 @@ var ReflectionClass = class {
37
124
  ModifiedClass
38
125
  });
39
126
  Object.setPrototypeOf(obj, proto);
40
- const methodNames = Object.getOwnPropertyNames(proto).filter((n) => n !== "constructor" && typeof proto[n] === "function");
41
- for (const methodName of methodNames) if (proto[methodName].toString().includes(`#${baseName}`)) {
42
- const boundMethod = ModifiedClass.prototype[methodName].bind(freshInstance);
43
- Object.defineProperty(obj, methodName, {
44
- value: boundMethod,
45
- writable: true,
46
- configurable: true
47
- });
127
+ const protoDescriptors = Object.getOwnPropertyDescriptors(proto);
128
+ for (const [propName, descriptor] of Object.entries(protoDescriptors)) {
129
+ if (propName === "constructor") continue;
130
+ if (typeof descriptor.value === "function") {
131
+ if (descriptor.value.toString().includes(`#${baseName}`)) {
132
+ const boundMethod = ModifiedClass.prototype[propName].bind(freshInstance);
133
+ Object.defineProperty(obj, propName, {
134
+ value: boundMethod,
135
+ writable: true,
136
+ configurable: true
137
+ });
138
+ }
139
+ }
140
+ if (descriptor.get || descriptor.set) {
141
+ const getterSource = descriptor.get?.toString() || "";
142
+ const setterSource = descriptor.set?.toString() || "";
143
+ if (getterSource.includes(`#${baseName}`) || setterSource.includes(`#${baseName}`)) {
144
+ const modifiedDescriptor = Object.getOwnPropertyDescriptor(ModifiedClass.prototype, propName);
145
+ if (modifiedDescriptor) {
146
+ const newDescriptor = {
147
+ configurable: true,
148
+ enumerable: descriptor.enumerable
149
+ };
150
+ if (modifiedDescriptor.get) newDescriptor.get = modifiedDescriptor.get.bind(freshInstance);
151
+ if (modifiedDescriptor.set) newDescriptor.set = modifiedDescriptor.set.bind(freshInstance);
152
+ Object.defineProperty(obj, propName, newDescriptor);
153
+ }
154
+ }
155
+ }
48
156
  }
49
157
  }
50
158
  async getProperty(name) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unreflect",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "Access and modify private class fields and methods in JavaScript",
5
5
  "repository": "KABBOUCHI/unreflect",
6
6
  "license": "MIT",