@iamevan/nobjc 0.0.2 → 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.
Binary file
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { NobjcNative } from './native.js';
1
+ import { NobjcNative } from "./native.js";
2
2
  declare class NobjcLibrary {
3
3
  [key: string]: NobjcObject;
4
4
  constructor(library: string);
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
- import { LoadLibrary, GetClassObject, ObjcObject } from './native.js';
1
+ import { LoadLibrary, GetClassObject, ObjcObject } from "./native.js";
2
+ const NATIVE_OBJC_OBJECT = Symbol("nativeObjcObject");
2
3
  class NobjcLibrary {
3
4
  constructor(library) {
4
5
  const handler = {
@@ -9,56 +10,70 @@ class NobjcLibrary {
9
10
  this.wasLoaded = true;
10
11
  }
11
12
  return new NobjcObject(GetClassObject(className));
12
- }
13
+ },
13
14
  };
14
15
  return new Proxy({}, handler);
15
16
  }
16
17
  }
17
18
  function NobjcMethodNameToObjcSelector(methodName) {
18
- return methodName.replace(/\$/g, ':');
19
+ return methodName.replace(/\$/g, ":");
19
20
  }
20
21
  // unused, might be useful for codegen later
21
22
  function ObjcSelectorToNobjcMethodName(selector) {
22
- return selector.replace(/:/g, '$');
23
+ return selector.replace(/:/g, "$");
23
24
  }
24
25
  class NobjcObject {
25
26
  constructor(object) {
26
27
  const handler = {
27
28
  has(target, p) {
28
- // guard against symbols
29
- if (typeof p === 'symbol')
29
+ // Return true for the special Symbol to enable unwrapping
30
+ if (p === NATIVE_OBJC_OBJECT)
31
+ return true;
32
+ // guard against other symbols
33
+ if (typeof p === "symbol")
30
34
  return Reflect.has(target, p);
31
35
  // toString is always present
32
- if (p === 'toString')
36
+ if (p === "toString")
33
37
  return true;
34
38
  // check if the object responds to the selector
35
- return target.$msgSend('respondsToSelector:', NobjcMethodNameToObjcSelector(p.toString()));
39
+ return target.$msgSend("respondsToSelector:", NobjcMethodNameToObjcSelector(p.toString()));
36
40
  },
37
- get(_, methodName, receiver) {
41
+ get(target, methodName, receiver) {
42
+ // Return the underlying native object when Symbol is accessed
43
+ if (methodName === NATIVE_OBJC_OBJECT) {
44
+ return target;
45
+ }
38
46
  // guard against symbols
39
- if (typeof methodName === 'symbol') {
47
+ if (typeof methodName === "symbol") {
40
48
  return Reflect.get(object, methodName, receiver);
41
49
  }
42
50
  // handle toString separately
43
- if (methodName === 'toString') {
44
- return () => String(object.$msgSend('description'));
51
+ if (methodName === "toString") {
52
+ return () => String(object.$msgSend("description"));
45
53
  }
46
54
  if (!(methodName in receiver)) {
47
55
  throw new Error(`Method ${methodName} not found on object ${receiver}`);
48
56
  }
49
57
  return new NobjcMethod(object, methodName);
50
- }
58
+ },
51
59
  };
52
60
  return new Proxy(object, handler);
53
61
  }
54
62
  }
63
+ function unwrapArg(arg) {
64
+ if (arg && typeof arg === "object" && NATIVE_OBJC_OBJECT in arg) {
65
+ return arg[NATIVE_OBJC_OBJECT];
66
+ }
67
+ return arg;
68
+ }
55
69
  class NobjcMethod {
56
70
  constructor(object, methodName) {
57
71
  const selector = NobjcMethodNameToObjcSelector(methodName);
58
72
  // This cannot be an arrow function because we need to access `arguments`.
59
73
  function methodFunc() {
60
- const result = object.$msgSend(selector, ...arguments);
61
- if (typeof result == 'object' && result instanceof ObjcObject) {
74
+ const unwrappedArgs = Array.from(arguments).map(unwrapArg);
75
+ const result = object.$msgSend(selector, ...unwrappedArgs);
76
+ if (typeof result == "object" && result instanceof ObjcObject) {
62
77
  return new NobjcObject(result);
63
78
  }
64
79
  return result;
package/package.json CHANGED
@@ -33,11 +33,12 @@
33
33
  "test-native": "node ./scripts/test-native-code.js",
34
34
  "test-js": "node ./scripts/test-js-code.js",
35
35
  "test-string-lifetime": "node ./scripts/test-string-lifetime.js",
36
- "test": "npm run test-native && npm run test-js && npm run test-string-lifetime",
36
+ "test-object-arguments": "node ./scripts/test-object-arguments.js",
37
+ "test": "npm run test-native && npm run test-js && npm run test-string-lifetime && npm run test-object-arguments",
37
38
  "make-clangd-config": "node ./scripts/make-clangd-config.js",
38
39
  "preinstall-disabled": "npm run build-scripts && npm run make-clangd-config"
39
40
  },
40
- "version": "0.0.2",
41
+ "version": "0.0.3",
41
42
  "description": "Objective-C bridge for Node.js",
42
43
  "main": "dist/index.js",
43
44
  "devDependencies": {