0
# JavaScript Integration
1
2
JavaScript execution environment and value management through Apple's JavaScriptCore framework. Provides a complete JavaScript interpreter that can execute JavaScript code, bridge between Python and JavaScript objects, handle exceptions, and manage JavaScript values within Python applications.
3
4
## Capabilities
5
6
### Core JavaScript Context
7
8
#### JSContext
9
10
JavaScript execution context that manages the global JavaScript environment.
11
12
```python { .api }
13
class JSContext:
14
def init(self) -> JSContext: ...
15
def initWithVirtualMachine_(self, virtualMachine: JSVirtualMachine) -> JSContext: ...
16
17
# Script execution
18
def evaluateScript_(self, script: str) -> JSValue: ...
19
def evaluateScript_withSourceURL_(self, script: str, sourceURL: NSURL) -> JSValue: ...
20
21
# Exception handling
22
@property
23
def exception(self) -> JSValue: ...
24
@property
25
def exceptionHandler(self) -> callable: ...
26
def setExceptionHandler_(self, handler: callable): ...
27
28
# Global object access
29
@property
30
def globalObject(self) -> JSValue: ...
31
32
# Virtual machine
33
@property
34
def virtualMachine(self) -> JSVirtualMachine: ...
35
36
# Inspection
37
def isInspectable(self) -> bool: ...
38
def setInspectable_(self, inspectable: bool): ...
39
@property
40
def name(self) -> str: ...
41
42
# Object lookup
43
def objectForKeyedSubscript_(self, key: str) -> JSValue: ...
44
def setObject_forKeyedSubscript_(self, object: JSValue, key: str): ...
45
```
46
47
#### JSVirtualMachine
48
49
JavaScript virtual machine for managing JavaScript execution.
50
51
```python { .api }
52
class JSVirtualMachine:
53
def init(self) -> JSVirtualMachine: ...
54
55
def addManagedReference_withOwner_(self, object: JSValue, owner: JSValue): ...
56
def removeManagedReference_withOwner_(self, object: JSValue, owner: JSValue): ...
57
```
58
59
### JavaScript Values
60
61
#### JSValue
62
63
Represents a JavaScript value and provides methods for type checking, conversion, and property access.
64
65
```python { .api }
66
class JSValue:
67
# Context creation
68
@classmethod
69
def valueWithObject_inContext_(cls, value: object, context: JSContext) -> JSValue: ...
70
@classmethod
71
def valueWithBool_inContext_(cls, value: bool, context: JSContext) -> JSValue: ...
72
@classmethod
73
def valueWithDouble_inContext_(cls, value: float, context: JSContext) -> JSValue: ...
74
@classmethod
75
def valueWithInt32_inContext_(cls, value: int, context: JSContext) -> JSValue: ...
76
@classmethod
77
def valueWithUInt32_inContext_(cls, value: int, context: JSContext) -> JSValue: ...
78
@classmethod
79
def valueWithPoint_inContext_(cls, point: CGPoint, context: JSContext) -> JSValue: ...
80
@classmethod
81
def valueWithRange_inContext_(cls, range: NSRange, context: JSContext) -> JSValue: ...
82
@classmethod
83
def valueWithRect_inContext_(cls, rect: CGRect, context: JSContext) -> JSValue: ...
84
@classmethod
85
def valueWithSize_inContext_(cls, size: CGSize, context: JSContext) -> JSValue: ...
86
@classmethod
87
def valueWithNullInContext_(cls, context: JSContext) -> JSValue: ...
88
@classmethod
89
def valueWithUndefinedInContext_(cls, context: JSContext) -> JSValue: ...
90
@classmethod
91
def valueWithNewObjectInContext_(cls, context: JSContext) -> JSValue: ...
92
@classmethod
93
def valueWithNewArrayInContext_(cls, context: JSContext) -> JSValue: ...
94
@classmethod
95
def valueWithNewRegularExpressionFromPattern_flags_inContext_(cls, pattern: str, flags: str, context: JSContext) -> JSValue: ...
96
@classmethod
97
def valueWithNewErrorFromMessage_inContext_(cls, message: str, context: JSContext) -> JSValue: ...
98
@classmethod
99
def valueWithNewPromiseInContext_fromExecutor_(cls, context: JSContext, executor: callable) -> JSValue: ...
100
@classmethod
101
def valueWithNewPromiseResolvedWithResult_inContext_(cls, result: JSValue, context: JSContext) -> JSValue: ...
102
@classmethod
103
def valueWithNewPromiseRejectedWithReason_inContext_(cls, reason: JSValue, context: JSContext) -> JSValue: ...
104
105
# Type checking
106
def isUndefined(self) -> bool: ...
107
def isNull(self) -> bool: ...
108
def isBoolean(self) -> bool: ...
109
def isNumber(self) -> bool: ...
110
def isString(self) -> bool: ...
111
def isObject(self) -> bool: ...
112
def isArray(self) -> bool: ...
113
def isDate(self) -> bool: ...
114
def isSymbol(self) -> bool: ...
115
116
# Type conversion
117
def toBool(self) -> bool: ...
118
def toNumber(self) -> float: ...
119
def toInt32(self) -> int: ...
120
def toUInt32(self) -> int: ...
121
def toString(self) -> str: ...
122
def toDate(self) -> NSDate: ...
123
def toArray(self) -> list: ...
124
def toDictionary(self) -> dict: ...
125
def toObject(self) -> object: ...
126
def toObjectOfClass_(self, expectedClass: type) -> object: ...
127
def toPoint(self) -> CGPoint: ...
128
def toRange(self) -> NSRange: ...
129
def toRect(self) -> CGRect: ...
130
def toSize(self) -> CGSize: ...
131
132
# Property access
133
def hasProperty_(self, property: str) -> bool: ...
134
def deleteProperty_(self, property: str) -> bool: ...
135
def valueForProperty_(self, property: str) -> JSValue: ...
136
def setValue_forProperty_(self, value: JSValue, property: str): ...
137
def defineProperty_descriptor_(self, property: str, descriptor: dict) -> bool: ...
138
139
# Array/object access
140
def valueAtIndex_(self, index: int) -> JSValue: ...
141
def setValue_atIndex_(self, value: JSValue, index: int): ...
142
def objectForKeyedSubscript_(self, key: str) -> JSValue: ...
143
def setObject_forKeyedSubscript_(self, object: JSValue, key: str): ...
144
def objectAtIndexedSubscript_(self, index: int) -> JSValue: ...
145
def setObject_atIndexedSubscript_(self, object: JSValue, index: int): ...
146
147
# Function calls
148
def callWithArguments_(self, arguments: list) -> JSValue: ...
149
def constructWithArguments_(self, arguments: list) -> JSValue: ...
150
def invokeMethod_withArguments_(self, method: str, arguments: list) -> JSValue: ...
151
152
# Comparison
153
def isEqualToObject_(self, value: JSValue) -> bool: ...
154
def isEqualWithTypeCoercionToObject_(self, value: JSValue) -> bool: ...
155
def isInstanceOf_(self, constructor: JSValue) -> bool: ...
156
157
# Context and prototype
158
@property
159
def context(self) -> JSContext: ...
160
@property
161
def prototype(self) -> JSValue: ...
162
def setPrototype_(self, prototype: JSValue): ...
163
```
164
165
#### JSManagedValue
166
167
Managed JavaScript value for memory management in Objective-C contexts.
168
169
```python { .api }
170
class JSManagedValue:
171
@classmethod
172
def managedValueWithValue_(cls, value: JSValue) -> JSManagedValue: ...
173
@classmethod
174
def managedValueWithValue_andOwner_(cls, value: JSValue, owner: object) -> JSManagedValue: ...
175
176
@property
177
def value(self) -> JSValue: ...
178
```
179
180
### Export System
181
182
#### JSExport Protocol
183
184
Base protocol for exporting Python classes to JavaScript.
185
186
```python { .api }
187
# JSExport is a protocol - implement in your Python classes
188
class MyExportedClass:
189
# Methods to be exported to JavaScript
190
def exportedMethod(self): ...
191
def anotherExportedMethod_(self, parameter): ...
192
```
193
194
#### JSExportAs Function
195
196
Decorator function for customizing JavaScript method names.
197
198
```python { .api }
199
def JSExportAs(PropertyName: str, Selector: callable) -> tuple:
200
"""
201
Export a Python method to JavaScript with a custom name.
202
203
Args:
204
PropertyName: The name to use in JavaScript
205
Selector: The Python method to export
206
207
Returns:
208
Tuple of selectors for the export system
209
"""
210
...
211
```
212
213
### Low-Level C API Functions
214
215
Direct access to JavaScriptCore C functions for advanced use cases.
216
217
#### Value Creation Functions
218
219
```python { .api }
220
def JSValueMakeString(context: JSContextRef, string: JSStringRef) -> JSValueRef: ...
221
def JSValueMakeNumber(context: JSContextRef, number: float) -> JSValueRef: ...
222
def JSValueMakeBoolean(context: JSContextRef, boolean: bool) -> JSValueRef: ...
223
def JSValueMakeNull(context: JSContextRef) -> JSValueRef: ...
224
def JSValueMakeUndefined(context: JSContextRef) -> JSValueRef: ...
225
```
226
227
#### Type Functions
228
229
```python { .api }
230
def JSValueGetType(context: JSContextRef, value: JSValueRef) -> JSType: ...
231
def JSValueToBoolean(context: JSContextRef, value: JSValueRef) -> bool: ...
232
def JSValueToNumber(context: JSContextRef, value: JSValueRef, exception: JSValueRef) -> float: ...
233
def JSValueCreateJSONString(context: JSContextRef, value: JSValueRef, indent: int, exception: JSValueRef) -> JSStringRef: ...
234
```
235
236
#### Object Functions
237
238
```python { .api }
239
def JSObjectSetPropertyForKey(context: JSContextRef, object: JSObjectRef, propertyKey: JSValueRef, value: JSValueRef, attributes: JSPropertyAttributes, exception: JSValueRef): ...
240
def JSObjectDeletePropertyForKey(context: JSContextRef, object: JSObjectRef, propertyKey: JSValueRef, exception: JSValueRef) -> bool: ...
241
def JSObjectMakeError(context: JSContextRef, argumentCount: int, arguments: JSValueRef, exception: JSValueRef) -> JSValueRef: ...
242
def JSObjectMakeTypedArray(context: JSContextRef, arrayType: JSTypedArrayType, length: int, exception: JSValueRef) -> JSValueRef: ...
243
def JSObjectGetArrayBufferBytesPtr(context: JSContextRef, object: JSObjectRef, exception: JSValueRef) -> bytes: ...
244
def JSObjectGetTypedArrayByteOffset(context: JSContextRef, object: JSObjectRef, exception: JSValueRef) -> int: ...
245
def JSValueGetTypedArrayType(context: JSContextRef, value: JSValueRef, exception: JSValueRef) -> JSTypedArrayType: ...
246
```
247
248
#### String Functions
249
250
```python { .api }
251
def JSStringCreateWithCFString(string: CFStringRef) -> JSStringRef: ...
252
def JSStringCopyCFString(allocator: CFAllocatorRef, string: JSStringRef) -> CFStringRef: ...
253
```
254
255
#### Memory Management Functions
256
257
```python { .api }
258
def JSClassRetain(jsClass: JSClassRef) -> JSClassRef: ...
259
```
260
261
### Constants and Types
262
263
#### JavaScript Types
264
265
```python { .api }
266
# JSType enumeration
267
kJSTypeUndefined = 0
268
kJSTypeNull = 1
269
kJSTypeBoolean = 2
270
kJSTypeNumber = 3
271
kJSTypeString = 4
272
kJSTypeObject = 5
273
kJSTypeSymbol = 6
274
```
275
276
#### Property Attributes
277
278
```python { .api }
279
# JSPropertyAttributes
280
kJSPropertyAttributeNone = 0
281
kJSPropertyAttributeReadOnly = 2
282
kJSPropertyAttributeDontEnum = 4
283
kJSPropertyAttributeDontDelete = 8
284
```
285
286
#### Class Attributes
287
288
```python { .api }
289
# JSClassAttributes
290
kJSClassAttributeNone = 0
291
kJSClassAttributeNoAutomaticPrototype = 2
292
```
293
294
#### Typed Array Types
295
296
```python { .api }
297
# JSTypedArrayType enumeration
298
kJSTypedArrayTypeInt8Array = 0
299
kJSTypedArrayTypeInt16Array = 1
300
kJSTypedArrayTypeInt32Array = 2
301
kJSTypedArrayTypeUint8Array = 3
302
kJSTypedArrayTypeUint8ClampedArray = 4
303
kJSTypedArrayTypeUint16Array = 5
304
kJSTypedArrayTypeUint32Array = 6
305
kJSTypedArrayTypeFloat32Array = 7
306
kJSTypedArrayTypeFloat64Array = 8
307
kJSTypedArrayTypeArrayBuffer = 9
308
kJSTypedArrayTypeNone = 10
309
kJSTypedArrayTypeBigInt64Array = 11
310
kJSTypedArrayTypeBigUint64Array = 12
311
```
312
313
#### Property Descriptor Keys
314
315
```python { .api }
316
JSPropertyDescriptorConfigurableKey = "configurable"
317
JSPropertyDescriptorEnumerableKey = "enumerable"
318
JSPropertyDescriptorGetKey = "get"
319
JSPropertyDescriptorSetKey = "set"
320
JSPropertyDescriptorValueKey = "value"
321
JSPropertyDescriptorWritableKey = "writable"
322
```
323
324
### Usage Examples
325
326
#### Basic JavaScript Execution
327
328
```python
329
import JavaScriptCore
330
331
# Create context
332
context = JavaScriptCore.JSContext.alloc().init()
333
334
# Execute JavaScript
335
result = context.evaluateScript_("2 + 3 * 4")
336
print(result.toNumber()) # Output: 14.0
337
338
# Work with JavaScript objects
339
context.evaluateScript_("var person = {name: 'John', age: 30};")
340
person = context.objectForKeyedSubscript_("person")
341
name = person.valueForProperty_("name")
342
print(name.toString()) # Output: John
343
```
344
345
#### Exception Handling
346
347
```python
348
import JavaScriptCore
349
350
context = JavaScriptCore.JSContext.alloc().init()
351
352
def exception_handler(context, exception):
353
print(f"JavaScript Error: {exception.toString()}")
354
print(f"Stack trace: {exception.valueForProperty_('stack').toString()}")
355
356
context.setExceptionHandler_(exception_handler)
357
358
# This will trigger the exception handler
359
context.evaluateScript_("throw new Error('Something went wrong');")
360
```
361
362
#### Exporting Python Objects to JavaScript
363
364
```python
365
import JavaScriptCore
366
from objc import protocol
367
368
@protocol("JSExport")
369
class Calculator:
370
def add_to_(self, a, b):
371
return a + b
372
373
def multiply_by_(self, a, b):
374
return a * b
375
376
context = JavaScriptCore.JSContext.alloc().init()
377
calculator = Calculator()
378
379
# Make calculator available in JavaScript
380
context.setObject_forKeyedSubscript_(calculator, "calculator")
381
382
# Use from JavaScript
383
result = context.evaluateScript_("calculator.add_to_(5, 3)")
384
print(result.toNumber()) # Output: 8.0
385
```
386
387
#### Working with JavaScript Arrays
388
389
```python
390
import JavaScriptCore
391
392
context = JavaScriptCore.JSContext.alloc().init()
393
394
# Create JavaScript array
395
js_array = JavaScriptCore.JSValue.valueWithNewArrayInContext_(context)
396
397
# Add elements
398
js_array.setValue_atIndex_(JavaScriptCore.JSValue.valueWithDouble_inContext_(1.5, context), 0)
399
js_array.setValue_atIndex_(JavaScriptCore.JSValue.valueWithObject_inContext_("hello", context), 1)
400
js_array.setValue_atIndex_(JavaScriptCore.JSValue.valueWithBool_inContext_(True, context), 2)
401
402
# Make available in JavaScript context
403
context.setObject_forKeyedSubscript_(js_array, "myArray")
404
405
# Access from JavaScript
406
length = context.evaluateScript_("myArray.length")
407
print(length.toNumber()) # Output: 3.0
408
409
first_element = context.evaluateScript_("myArray[0]")
410
print(first_element.toNumber()) # Output: 1.5
411
```
412
413
#### Promise Handling
414
415
```python
416
import JavaScriptCore
417
418
context = JavaScriptCore.JSContext.alloc().init()
419
420
def promise_executor(resolve, reject):
421
# Simulate async operation
422
import time
423
time.sleep(0.1)
424
resolve.callWithArguments_(["Success!"])
425
426
# Create promise
427
promise = JavaScriptCore.JSValue.valueWithNewPromiseInContext_fromExecutor_(context, promise_executor)
428
429
# Make available in JavaScript
430
context.setObject_forKeyedSubscript_(promise, "myPromise")
431
432
# Handle promise in JavaScript
433
context.evaluateScript_("""
434
myPromise.then(function(result) {
435
console.log('Promise resolved:', result);
436
}).catch(function(error) {
437
console.log('Promise rejected:', error);
438
});
439
""")
440
```