pyodide 0.19.0 → 0.19.1
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/error_handling.gen.ts +294 -0
- package/package.json +1 -1
- package/{pyproxy.gen.js → pyproxy.gen.ts} +386 -527
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// This file is generated by applying the C preprocessor to core/pyproxy.
|
|
1
|
+
// This file is generated by applying the C preprocessor to core/pyproxy.ts
|
|
2
2
|
// It uses the macros defined in core/pyproxy.c
|
|
3
3
|
// Do not edit it directly!
|
|
4
4
|
|
|
@@ -21,112 +21,6 @@
|
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
24
|
/**
|
|
131
25
|
* Every public Python entrypoint goes through this file! The main entrypoint is
|
|
132
26
|
* the callPyObject method, but of course one can also execute arbitrary code
|
|
@@ -140,33 +34,34 @@
|
|
|
140
34
|
* any macros available in pyproxy.c are available here. We only need the flags
|
|
141
35
|
* macros HAS_LENGTH, etc.
|
|
142
36
|
*
|
|
143
|
-
* See Makefile recipe for src/js/pyproxy.
|
|
37
|
+
* See Makefile recipe for src/js/pyproxy.gen.ts
|
|
144
38
|
*/
|
|
145
|
-
|
|
146
|
-
import { Module } from "./module.js";
|
|
147
|
-
|
|
39
|
+
import { Module, API, Hiwire } from "./module.js";
|
|
148
40
|
/**
|
|
149
41
|
* Is the argument a :any:`PyProxy`?
|
|
150
|
-
* @param jsobj
|
|
151
|
-
* @returns
|
|
42
|
+
* @param jsobj Object to test.
|
|
43
|
+
* @returns Is ``jsobj`` a :any:`PyProxy`?
|
|
152
44
|
*/
|
|
153
|
-
export function isPyProxy(jsobj) {
|
|
45
|
+
export function isPyProxy(jsobj: any): jsobj is PyProxy {
|
|
154
46
|
return !!jsobj && jsobj.$$ !== undefined && jsobj.$$.type === "PyProxy";
|
|
155
47
|
}
|
|
156
|
-
|
|
157
|
-
|
|
48
|
+
API.isPyProxy = isPyProxy;
|
|
49
|
+
declare var FinalizationRegistry: any;
|
|
50
|
+
declare var globalThis: any;
|
|
158
51
|
if (globalThis.FinalizationRegistry) {
|
|
159
|
-
Module.finalizationRegistry = new FinalizationRegistry(
|
|
160
|
-
cache
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
52
|
+
Module.finalizationRegistry = new FinalizationRegistry(
|
|
53
|
+
([ptr, cache]: [ptr: number, cache: PyProxyCache]) => {
|
|
54
|
+
cache.leaked = (!!1);
|
|
55
|
+
pyproxy_decref_cache(cache);
|
|
56
|
+
try {
|
|
57
|
+
Module._Py_DecRef(ptr);
|
|
58
|
+
} catch (e) {
|
|
59
|
+
// I'm not really sure what happens if an error occurs inside of a
|
|
60
|
+
// finalizer...
|
|
61
|
+
API.fatal_error(e);
|
|
62
|
+
}
|
|
168
63
|
}
|
|
169
|
-
|
|
64
|
+
);
|
|
170
65
|
// For some unclear reason this code screws up selenium FirefoxDriver. Works
|
|
171
66
|
// fine in chrome and when I test it in browser. It seems to be sensitive to
|
|
172
67
|
// changes that don't make a difference to the semantics.
|
|
@@ -176,35 +71,33 @@ if (globalThis.FinalizationRegistry) {
|
|
|
176
71
|
// Module._PyBuffer_Release(ptr);
|
|
177
72
|
// Module._PyMem_Free(ptr);
|
|
178
73
|
// } catch (e) {
|
|
179
|
-
//
|
|
74
|
+
// API.fatal_error(e);
|
|
180
75
|
// }
|
|
181
76
|
// });
|
|
182
77
|
} else {
|
|
183
78
|
Module.finalizationRegistry = { register() {}, unregister() {} };
|
|
184
79
|
// Module.bufferFinalizationRegistry = finalizationRegistry;
|
|
185
80
|
}
|
|
186
|
-
|
|
187
81
|
let pyproxy_alloc_map = new Map();
|
|
188
82
|
Module.pyproxy_alloc_map = pyproxy_alloc_map;
|
|
189
|
-
let trace_pyproxy_alloc;
|
|
190
|
-
let trace_pyproxy_dealloc;
|
|
191
|
-
|
|
83
|
+
let trace_pyproxy_alloc: (proxy: any) => void;
|
|
84
|
+
let trace_pyproxy_dealloc: (proxy: any) => void;
|
|
192
85
|
Module.enable_pyproxy_allocation_tracing = function () {
|
|
193
|
-
trace_pyproxy_alloc = function (proxy) {
|
|
86
|
+
trace_pyproxy_alloc = function (proxy: any) {
|
|
194
87
|
pyproxy_alloc_map.set(proxy, Error().stack);
|
|
195
88
|
};
|
|
196
|
-
trace_pyproxy_dealloc = function (proxy) {
|
|
89
|
+
trace_pyproxy_dealloc = function (proxy: any) {
|
|
197
90
|
pyproxy_alloc_map.delete(proxy);
|
|
198
91
|
};
|
|
199
92
|
};
|
|
200
93
|
Module.disable_pyproxy_allocation_tracing = function () {
|
|
201
|
-
trace_pyproxy_alloc = function (proxy) {};
|
|
202
|
-
trace_pyproxy_dealloc = function (proxy) {};
|
|
94
|
+
trace_pyproxy_alloc = function (proxy: any) {};
|
|
95
|
+
trace_pyproxy_dealloc = function (proxy: any) {};
|
|
203
96
|
};
|
|
204
97
|
Module.disable_pyproxy_allocation_tracing();
|
|
205
|
-
|
|
98
|
+
type PyProxyCache = { cacheId: number; refcnt: number; leaked?: boolean };
|
|
206
99
|
/**
|
|
207
|
-
* Create a new PyProxy
|
|
100
|
+
* Create a new PyProxy wrapping ptrobj which is a PyObject*.
|
|
208
101
|
*
|
|
209
102
|
* The argument cache is only needed to implement the PyProxy.copy API, it
|
|
210
103
|
* allows the copy of the PyProxy to share its attribute cache with the original
|
|
@@ -216,7 +109,7 @@ Module.disable_pyproxy_allocation_tracing();
|
|
|
216
109
|
* many as possible.
|
|
217
110
|
* @private
|
|
218
111
|
*/
|
|
219
|
-
Module.pyproxy_new = function (ptrobj, cache) {
|
|
112
|
+
Module.pyproxy_new = function (ptrobj: number, cache?: PyProxyCache) {
|
|
220
113
|
let flags = Module._pyproxy_getflags(ptrobj);
|
|
221
114
|
let cls = Module.getPyProxyClass(flags);
|
|
222
115
|
// Reflect.construct calls the constructor of Module.PyProxyClass but sets
|
|
@@ -241,7 +134,7 @@ Module.pyproxy_new = function (ptrobj, cache) {
|
|
|
241
134
|
if (!cache) {
|
|
242
135
|
// The cache needs to be accessed primarily from the C function
|
|
243
136
|
// _pyproxy_getattr so we make a hiwire id.
|
|
244
|
-
let cacheId =
|
|
137
|
+
let cacheId = Hiwire.new_value(new Map());
|
|
245
138
|
cache = { cacheId, refcnt: 0 };
|
|
246
139
|
}
|
|
247
140
|
cache.refcnt++;
|
|
@@ -254,33 +147,24 @@ Module.pyproxy_new = function (ptrobj, cache) {
|
|
|
254
147
|
Module.finalizationRegistry.register(proxy, [ptrobj, cache], proxy);
|
|
255
148
|
return proxy;
|
|
256
149
|
};
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
throw new Error(
|
|
262
|
-
jsobj.$$.destroyed_msg || "Object has already been destroyed"
|
|
263
|
-
);
|
|
150
|
+
function _getPtr(jsobj: any) {
|
|
151
|
+
let ptr: number = jsobj.$$.ptr;
|
|
152
|
+
if (ptr === 0) {
|
|
153
|
+
throw new Error(jsobj.$$.destroyed_msg);
|
|
264
154
|
}
|
|
265
155
|
return ptr;
|
|
266
156
|
}
|
|
267
|
-
|
|
268
157
|
let pyproxyClassMap = new Map();
|
|
269
158
|
/**
|
|
270
|
-
*
|
|
159
|
+
* Retrieve the appropriate mixins based on the features requested in flags.
|
|
271
160
|
* Used by pyproxy_new. The "flags" variable is produced by the C function
|
|
272
161
|
* pyproxy_getflags. Multiple PyProxies with the same set of feature flags
|
|
273
162
|
* will share the same prototype, so the memory footprint of each individual
|
|
274
163
|
* PyProxy is minimal.
|
|
275
164
|
* @private
|
|
276
165
|
*/
|
|
277
|
-
Module.getPyProxyClass = function (flags) {
|
|
278
|
-
|
|
279
|
-
if (result) {
|
|
280
|
-
return result;
|
|
281
|
-
}
|
|
282
|
-
let descriptors = {};
|
|
283
|
-
for (let [feature_flag, methods] of [
|
|
166
|
+
Module.getPyProxyClass = function (flags: number) {
|
|
167
|
+
const FLAG_TYPE_PAIRS: [number, any][] = [
|
|
284
168
|
[(1 << 0), PyProxyLengthMethods],
|
|
285
169
|
[(1 << 1), PyProxyGetItemMethods],
|
|
286
170
|
[(1 << 2), PyProxySetItemMethods],
|
|
@@ -290,7 +174,13 @@ Module.getPyProxyClass = function (flags) {
|
|
|
290
174
|
[(1 << 6), PyProxyAwaitableMethods],
|
|
291
175
|
[(1 << 7), PyProxyBufferMethods],
|
|
292
176
|
[(1 << 8), PyProxyCallableMethods],
|
|
293
|
-
]
|
|
177
|
+
];
|
|
178
|
+
let result = pyproxyClassMap.get(flags);
|
|
179
|
+
if (result) {
|
|
180
|
+
return result;
|
|
181
|
+
}
|
|
182
|
+
let descriptors: any = {};
|
|
183
|
+
for (let [feature_flag, methods] of FLAG_TYPE_PAIRS) {
|
|
294
184
|
if (flags & feature_flag) {
|
|
295
185
|
Object.assign(
|
|
296
186
|
descriptors,
|
|
@@ -313,54 +203,64 @@ Module.getPyProxyClass = function (flags) {
|
|
|
313
203
|
pyproxyClassMap.set(flags, NewPyProxyClass);
|
|
314
204
|
return NewPyProxyClass;
|
|
315
205
|
};
|
|
316
|
-
|
|
317
206
|
// Static methods
|
|
318
207
|
Module.PyProxy_getPtr = _getPtr;
|
|
319
|
-
|
|
320
208
|
const pyproxy_cache_destroyed_msg =
|
|
321
209
|
"This borrowed attribute proxy was automatically destroyed in the " +
|
|
322
210
|
"process of destroying the proxy it was borrowed from. Try using the 'copy' method.";
|
|
323
|
-
|
|
324
|
-
function pyproxy_decref_cache(cache) {
|
|
211
|
+
function pyproxy_decref_cache(cache: PyProxyCache) {
|
|
325
212
|
if (!cache) {
|
|
326
213
|
return;
|
|
327
214
|
}
|
|
328
215
|
cache.refcnt--;
|
|
329
216
|
if (cache.refcnt === 0) {
|
|
330
|
-
let cache_map =
|
|
217
|
+
let cache_map = Hiwire.pop_value(cache.cacheId);
|
|
331
218
|
for (let proxy_id of cache_map.values()) {
|
|
332
|
-
const cache_entry =
|
|
219
|
+
const cache_entry = Hiwire.pop_value(proxy_id);
|
|
333
220
|
if (!cache.leaked) {
|
|
334
221
|
Module.pyproxy_destroy(cache_entry, pyproxy_cache_destroyed_msg);
|
|
335
222
|
}
|
|
336
223
|
}
|
|
337
224
|
}
|
|
338
225
|
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
if (proxy.$$.ptr === null) {
|
|
226
|
+
Module.pyproxy_destroy = function (proxy: PyProxy, destroyed_msg: string) {
|
|
227
|
+
if (proxy.$$.ptr === 0) {
|
|
342
228
|
return;
|
|
343
229
|
}
|
|
344
230
|
let ptrobj = _getPtr(proxy);
|
|
345
231
|
Module.finalizationRegistry.unregister(proxy);
|
|
232
|
+
destroyed_msg = destroyed_msg || "Object has already been destroyed";
|
|
233
|
+
let proxy_type = proxy.type;
|
|
234
|
+
let proxy_repr;
|
|
235
|
+
try {
|
|
236
|
+
proxy_repr = proxy.toString();
|
|
237
|
+
} catch (e) {
|
|
238
|
+
if (e.pyodide_fatal_error) {
|
|
239
|
+
throw e;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
346
242
|
// Maybe the destructor will call JavaScript code that will somehow try
|
|
347
243
|
// to use this proxy. Mark it deleted before decrementing reference count
|
|
348
244
|
// just in case!
|
|
349
|
-
proxy.$$.ptr =
|
|
245
|
+
proxy.$$.ptr = 0;
|
|
246
|
+
destroyed_msg += "\n" + `The object was of type "${proxy_type}" and `;
|
|
247
|
+
if (proxy_repr) {
|
|
248
|
+
destroyed_msg += `had repr "${proxy_repr}"`;
|
|
249
|
+
} else {
|
|
250
|
+
destroyed_msg += "an error was raised when trying to generate its repr";
|
|
251
|
+
}
|
|
350
252
|
proxy.$$.destroyed_msg = destroyed_msg;
|
|
351
253
|
pyproxy_decref_cache(proxy.$$.cache);
|
|
352
254
|
try {
|
|
353
255
|
Module._Py_DecRef(ptrobj);
|
|
354
256
|
trace_pyproxy_dealloc(proxy);
|
|
355
257
|
} catch (e) {
|
|
356
|
-
|
|
258
|
+
API.fatal_error(e);
|
|
357
259
|
}
|
|
358
260
|
};
|
|
359
|
-
|
|
360
261
|
// Now a lot of boilerplate to wrap the abstract Object protocol wrappers
|
|
361
262
|
// defined in pyproxy.c in JavaScript functions.
|
|
362
|
-
|
|
363
|
-
Module.callPyObjectKwargs = function (ptrobj, ...jsargs) {
|
|
263
|
+
Module.callPyObjectKwargs = function (ptrobj: number, ...jsargs: any) {
|
|
364
264
|
// We don't do any checking for kwargs, checks are in PyProxy.callKwargs
|
|
365
265
|
// which only is used when the keyword arguments come from the user.
|
|
366
266
|
let kwargs = jsargs.pop();
|
|
@@ -369,9 +269,8 @@ Module.callPyObjectKwargs = function (ptrobj, ...jsargs) {
|
|
|
369
269
|
let kwargs_values = Object.values(kwargs);
|
|
370
270
|
let num_kwargs = kwargs_names.length;
|
|
371
271
|
jsargs.push(...kwargs_values);
|
|
372
|
-
|
|
373
|
-
let
|
|
374
|
-
let idkwnames = Module.hiwire.new_value(kwargs_names);
|
|
272
|
+
let idargs = Hiwire.new_value(jsargs);
|
|
273
|
+
let idkwnames = Hiwire.new_value(kwargs_names);
|
|
375
274
|
let idresult;
|
|
376
275
|
try {
|
|
377
276
|
idresult = Module.__pyproxy_apply(
|
|
@@ -382,30 +281,27 @@ Module.callPyObjectKwargs = function (ptrobj, ...jsargs) {
|
|
|
382
281
|
num_kwargs
|
|
383
282
|
);
|
|
384
283
|
} catch (e) {
|
|
385
|
-
|
|
284
|
+
API.fatal_error(e);
|
|
386
285
|
} finally {
|
|
387
|
-
|
|
388
|
-
|
|
286
|
+
Hiwire.decref(idargs);
|
|
287
|
+
Hiwire.decref(idkwnames);
|
|
389
288
|
}
|
|
390
289
|
if (idresult === 0) {
|
|
391
290
|
Module._pythonexc2js();
|
|
392
291
|
}
|
|
393
|
-
return
|
|
292
|
+
return Hiwire.pop_value(idresult);
|
|
394
293
|
};
|
|
395
|
-
|
|
396
|
-
Module.callPyObject = function (ptrobj, ...jsargs) {
|
|
294
|
+
Module.callPyObject = function (ptrobj: number, ...jsargs: any) {
|
|
397
295
|
return Module.callPyObjectKwargs(ptrobj, ...jsargs, {});
|
|
398
296
|
};
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
*/
|
|
404
|
-
class PyProxyClass {
|
|
297
|
+
export type PyProxy = PyProxyClass & { [x: string]: any };
|
|
298
|
+
export class PyProxyClass {
|
|
299
|
+
$$: { ptr: number; cache: PyProxyCache; destroyed_msg?: string };
|
|
300
|
+
$$flags: number;
|
|
301
|
+
/** @private */
|
|
405
302
|
constructor() {
|
|
406
303
|
throw new TypeError("PyProxy is not a constructor");
|
|
407
304
|
}
|
|
408
|
-
|
|
409
305
|
get [Symbol.toStringTag]() {
|
|
410
306
|
return "PyProxy";
|
|
411
307
|
}
|
|
@@ -423,51 +319,45 @@ class PyProxyClass {
|
|
|
423
319
|
* else:
|
|
424
320
|
* ty.__module__ + "." + ty.__name__
|
|
425
321
|
*
|
|
426
|
-
* @type {string}
|
|
427
322
|
*/
|
|
428
|
-
get type() {
|
|
323
|
+
get type(): string {
|
|
429
324
|
let ptrobj = _getPtr(this);
|
|
430
|
-
return
|
|
325
|
+
return Hiwire.pop_value(Module.__pyproxy_type(ptrobj));
|
|
431
326
|
}
|
|
432
|
-
|
|
433
|
-
* @returns {string}
|
|
434
|
-
*/
|
|
435
|
-
toString() {
|
|
327
|
+
toString(): string {
|
|
436
328
|
let ptrobj = _getPtr(this);
|
|
437
329
|
let jsref_repr;
|
|
438
330
|
try {
|
|
439
331
|
jsref_repr = Module.__pyproxy_repr(ptrobj);
|
|
440
332
|
} catch (e) {
|
|
441
|
-
|
|
333
|
+
API.fatal_error(e);
|
|
442
334
|
}
|
|
443
335
|
if (jsref_repr === 0) {
|
|
444
336
|
Module._pythonexc2js();
|
|
445
337
|
}
|
|
446
|
-
return
|
|
338
|
+
return Hiwire.pop_value(jsref_repr);
|
|
447
339
|
}
|
|
448
340
|
/**
|
|
449
|
-
* Destroy the ``PyProxy``. This will release the memory. Any further
|
|
450
|
-
*
|
|
341
|
+
* Destroy the ``PyProxy``. This will release the memory. Any further attempt
|
|
342
|
+
* to use the object will raise an error.
|
|
451
343
|
*
|
|
452
344
|
* In a browser supporting `FinalizationRegistry
|
|
453
345
|
* <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/FinalizationRegistry>`_
|
|
454
346
|
* Pyodide will automatically destroy the ``PyProxy`` when it is garbage
|
|
455
|
-
* collected, however there is no guarantee that the finalizer will be run
|
|
456
|
-
*
|
|
347
|
+
* collected, however there is no guarantee that the finalizer will be run in
|
|
348
|
+
* a timely manner so it is better to ``destroy`` the proxy explicitly.
|
|
457
349
|
*
|
|
458
|
-
* @param
|
|
459
|
-
*
|
|
460
|
-
* destroyed".
|
|
350
|
+
* @param destroyed_msg The error message to print if use is attempted after
|
|
351
|
+
* destroying. Defaults to "Object has already been destroyed".
|
|
461
352
|
*/
|
|
462
|
-
destroy(destroyed_msg) {
|
|
353
|
+
destroy(destroyed_msg?: string) {
|
|
463
354
|
Module.pyproxy_destroy(this, destroyed_msg);
|
|
464
355
|
}
|
|
465
356
|
/**
|
|
466
357
|
* Make a new PyProxy pointing to the same Python object.
|
|
467
358
|
* Useful if the PyProxy is destroyed somewhere else.
|
|
468
|
-
* @returns {PyProxy}
|
|
469
359
|
*/
|
|
470
|
-
copy() {
|
|
360
|
+
copy(): PyProxy {
|
|
471
361
|
let ptrobj = _getPtr(this);
|
|
472
362
|
return Module.pyproxy_new(ptrobj, this.$$.cache);
|
|
473
363
|
}
|
|
@@ -476,125 +366,141 @@ class PyProxyClass {
|
|
|
476
366
|
* default does a deep conversion, if a shallow conversion is desired, you can
|
|
477
367
|
* use ``proxy.toJs({depth : 1})``. See :ref:`Explicit Conversion of PyProxy
|
|
478
368
|
* <type-translations-pyproxy-to-js>` for more info.
|
|
479
|
-
*
|
|
480
|
-
* @
|
|
481
|
-
* @param {number} [options.depth] How many layers deep to perform the
|
|
482
|
-
* conversion. Defaults to infinite.
|
|
483
|
-
* @param {array} [options.pyproxies] If provided, ``toJs`` will store all
|
|
484
|
-
* PyProxies created in this list. This allows you to easily destroy all the
|
|
485
|
-
* PyProxies by iterating the list without having to recurse over the
|
|
486
|
-
* generated structure. The most common use case is to create a new empty
|
|
487
|
-
* list, pass the list as `pyproxies`, and then later iterate over `pyproxies`
|
|
488
|
-
* to destroy all of created proxies.
|
|
489
|
-
* @param {boolean} [options.create_pyproxies] If false, ``toJs`` will throw a
|
|
490
|
-
* ``ConversionError`` rather than producing a ``PyProxy``.
|
|
491
|
-
* @param {boolean} [options.dict_converter] A function to be called on an
|
|
492
|
-
* iterable of pairs ``[key, value]``. Convert this iterable of pairs to the
|
|
493
|
-
* desired output. For instance, ``Object.fromEntries`` would convert the dict
|
|
494
|
-
* to an object, ``Array.from`` converts it to an array of entries, and ``(it) =>
|
|
495
|
-
* new Map(it)`` converts it to a ``Map`` (which is the default behavior).
|
|
496
|
-
* @return {any} The JavaScript object resulting from the conversion.
|
|
369
|
+
* @param options
|
|
370
|
+
* @return The JavaScript object resulting from the conversion.
|
|
497
371
|
*/
|
|
498
372
|
toJs({
|
|
499
373
|
depth = -1,
|
|
500
|
-
pyproxies,
|
|
374
|
+
pyproxies = undefined,
|
|
501
375
|
create_pyproxies = (!!1),
|
|
502
|
-
dict_converter,
|
|
503
|
-
|
|
376
|
+
dict_converter = undefined,
|
|
377
|
+
default_converter = undefined,
|
|
378
|
+
}: {
|
|
379
|
+
/** How many layers deep to perform the conversion. Defaults to infinite */
|
|
380
|
+
depth?: number;
|
|
381
|
+
/**
|
|
382
|
+
* If provided, ``toJs`` will store all PyProxies created in this list. This
|
|
383
|
+
* allows you to easily destroy all the PyProxies by iterating the list
|
|
384
|
+
* without having to recurse over the generated structure. The most common
|
|
385
|
+
* use case is to create a new empty list, pass the list as `pyproxies`, and
|
|
386
|
+
* then later iterate over `pyproxies` to destroy all of created proxies.
|
|
387
|
+
*/
|
|
388
|
+
pyproxies?: PyProxy[];
|
|
389
|
+
/**
|
|
390
|
+
* If false, ``toJs`` will throw a ``ConversionError`` rather than
|
|
391
|
+
* producing a ``PyProxy``.
|
|
392
|
+
*/
|
|
393
|
+
create_pyproxies?: boolean;
|
|
394
|
+
/**
|
|
395
|
+
* A function to be called on an iterable of pairs ``[key, value]``. Convert
|
|
396
|
+
* this iterable of pairs to the desired output. For instance,
|
|
397
|
+
* ``Object.fromEntries`` would convert the dict to an object, ``Array.from``
|
|
398
|
+
* converts it to an array of entries, and ``(it) => new Map(it)`` converts
|
|
399
|
+
* it to a ``Map`` (which is the default behavior).
|
|
400
|
+
*/
|
|
401
|
+
dict_converter?: (array: Iterable<[key: string, value: any]>) => any;
|
|
402
|
+
/**
|
|
403
|
+
* Optional argument to convert objects with no default conversion. See the
|
|
404
|
+
* documentation of :any:`pyodide.to_js`.
|
|
405
|
+
*/
|
|
406
|
+
default_converter?: (
|
|
407
|
+
obj: PyProxy,
|
|
408
|
+
convert: (obj: PyProxy) => any,
|
|
409
|
+
cacheConversion: (obj: PyProxy, result: any) => void
|
|
410
|
+
) => any;
|
|
411
|
+
} = {}): any {
|
|
504
412
|
let ptrobj = _getPtr(this);
|
|
505
413
|
let idresult;
|
|
506
414
|
let proxies_id;
|
|
507
415
|
let dict_converter_id = 0;
|
|
416
|
+
let default_converter_id = 0;
|
|
508
417
|
if (!create_pyproxies) {
|
|
509
418
|
proxies_id = 0;
|
|
510
419
|
} else if (pyproxies) {
|
|
511
|
-
proxies_id =
|
|
420
|
+
proxies_id = Hiwire.new_value(pyproxies);
|
|
512
421
|
} else {
|
|
513
|
-
proxies_id =
|
|
422
|
+
proxies_id = Hiwire.new_value([]);
|
|
514
423
|
}
|
|
515
424
|
if (dict_converter) {
|
|
516
|
-
dict_converter_id =
|
|
425
|
+
dict_converter_id = Hiwire.new_value(dict_converter);
|
|
426
|
+
}
|
|
427
|
+
if (default_converter) {
|
|
428
|
+
default_converter_id = Hiwire.new_value(default_converter);
|
|
517
429
|
}
|
|
518
430
|
try {
|
|
519
|
-
idresult = Module.
|
|
431
|
+
idresult = Module._python2js_custom(
|
|
520
432
|
ptrobj,
|
|
521
433
|
depth,
|
|
522
434
|
proxies_id,
|
|
523
|
-
dict_converter_id
|
|
435
|
+
dict_converter_id,
|
|
436
|
+
default_converter_id
|
|
524
437
|
);
|
|
525
438
|
} catch (e) {
|
|
526
|
-
|
|
439
|
+
API.fatal_error(e);
|
|
527
440
|
} finally {
|
|
528
|
-
|
|
529
|
-
|
|
441
|
+
Hiwire.decref(proxies_id);
|
|
442
|
+
Hiwire.decref(dict_converter_id);
|
|
443
|
+
Hiwire.decref(default_converter_id);
|
|
530
444
|
}
|
|
531
445
|
if (idresult === 0) {
|
|
532
446
|
Module._pythonexc2js();
|
|
533
447
|
}
|
|
534
|
-
return
|
|
448
|
+
return Hiwire.pop_value(idresult);
|
|
535
449
|
}
|
|
536
450
|
/**
|
|
537
451
|
* Check whether the :any:`PyProxy.length` getter is available on this PyProxy. A
|
|
538
452
|
* Typescript type guard.
|
|
539
|
-
* @returns {this is PyProxyWithLength}
|
|
540
453
|
*/
|
|
541
|
-
supportsLength() {
|
|
454
|
+
supportsLength(): this is PyProxyWithLength {
|
|
542
455
|
return !!(this.$$flags & (1 << 0));
|
|
543
456
|
}
|
|
544
457
|
/**
|
|
545
458
|
* Check whether the :any:`PyProxy.get` method is available on this PyProxy. A
|
|
546
459
|
* Typescript type guard.
|
|
547
|
-
* @returns {this is PyProxyWithGet}
|
|
548
460
|
*/
|
|
549
|
-
supportsGet() {
|
|
461
|
+
supportsGet(): this is PyProxyWithGet {
|
|
550
462
|
return !!(this.$$flags & (1 << 1));
|
|
551
463
|
}
|
|
552
464
|
/**
|
|
553
465
|
* Check whether the :any:`PyProxy.set` method is available on this PyProxy. A
|
|
554
466
|
* Typescript type guard.
|
|
555
|
-
* @returns {this is PyProxyWithSet}
|
|
556
467
|
*/
|
|
557
|
-
supportsSet() {
|
|
468
|
+
supportsSet(): this is PyProxyWithSet {
|
|
558
469
|
return !!(this.$$flags & (1 << 2));
|
|
559
470
|
}
|
|
560
471
|
/**
|
|
561
472
|
* Check whether the :any:`PyProxy.has` method is available on this PyProxy. A
|
|
562
473
|
* Typescript type guard.
|
|
563
|
-
* @returns {this is PyProxyWithHas}
|
|
564
474
|
*/
|
|
565
|
-
supportsHas() {
|
|
475
|
+
supportsHas(): this is PyProxyWithHas {
|
|
566
476
|
return !!(this.$$flags & (1 << 3));
|
|
567
477
|
}
|
|
568
478
|
/**
|
|
569
479
|
* Check whether the PyProxy is iterable. A Typescript type guard for
|
|
570
|
-
* :any:`PyProxy.[
|
|
571
|
-
* @returns {this is PyProxyIterable}
|
|
480
|
+
* :any:`PyProxy.[iterator]`.
|
|
572
481
|
*/
|
|
573
|
-
isIterable() {
|
|
482
|
+
isIterable(): this is PyProxyIterable {
|
|
574
483
|
return !!(this.$$flags & ((1 << 4) | (1 << 5)));
|
|
575
484
|
}
|
|
576
485
|
/**
|
|
577
486
|
* Check whether the PyProxy is iterable. A Typescript type guard for
|
|
578
487
|
* :any:`PyProxy.next`.
|
|
579
|
-
* @returns {this is PyProxyIterator}
|
|
580
488
|
*/
|
|
581
|
-
isIterator() {
|
|
489
|
+
isIterator(): this is PyProxyIterator {
|
|
582
490
|
return !!(this.$$flags & (1 << 5));
|
|
583
491
|
}
|
|
584
492
|
/**
|
|
585
493
|
* Check whether the PyProxy is awaitable. A Typescript type guard, if this
|
|
586
494
|
* function returns true Typescript considers the PyProxy to be a ``Promise``.
|
|
587
|
-
* @returns {this is PyProxyAwaitable}
|
|
588
495
|
*/
|
|
589
|
-
isAwaitable() {
|
|
496
|
+
isAwaitable(): this is PyProxyAwaitable {
|
|
590
497
|
return !!(this.$$flags & (1 << 6));
|
|
591
498
|
}
|
|
592
499
|
/**
|
|
593
500
|
* Check whether the PyProxy is a buffer. A Typescript type guard for
|
|
594
501
|
* :any:`PyProxy.getBuffer`.
|
|
595
|
-
* @returns {this is PyProxyBuffer}
|
|
596
502
|
*/
|
|
597
|
-
isBuffer() {
|
|
503
|
+
isBuffer(): this is PyProxyBuffer {
|
|
598
504
|
return !!(this.$$flags & (1 << 7));
|
|
599
505
|
}
|
|
600
506
|
/**
|
|
@@ -602,32 +508,27 @@ class PyProxyClass {
|
|
|
602
508
|
* returns true then Typescript considers the Proxy to be callable of
|
|
603
509
|
* signature ``(args... : any[]) => PyProxy | number | bigint | string |
|
|
604
510
|
* boolean | undefined``.
|
|
605
|
-
* @returns {this is PyProxyCallable}
|
|
606
511
|
*/
|
|
607
|
-
isCallable() {
|
|
512
|
+
isCallable(): this is PyProxyCallable {
|
|
608
513
|
return !!(this.$$flags & (1 << 8));
|
|
609
514
|
}
|
|
610
515
|
}
|
|
611
|
-
|
|
612
|
-
/**
|
|
613
|
-
* @typedef { PyProxy & PyProxyLengthMethods } PyProxyWithLength
|
|
614
|
-
*/
|
|
516
|
+
export type PyProxyWithLength = PyProxy & PyProxyLengthMethods;
|
|
615
517
|
// Controlled by HAS_LENGTH, appears for any object with __len__ or sq_length
|
|
616
518
|
// or mp_length methods
|
|
617
|
-
class PyProxyLengthMethods {
|
|
519
|
+
export class PyProxyLengthMethods {
|
|
618
520
|
/**
|
|
619
521
|
* The length of the object.
|
|
620
522
|
*
|
|
621
523
|
* Present only if the proxied Python object has a ``__len__`` method.
|
|
622
|
-
* @returns {number}
|
|
623
524
|
*/
|
|
624
|
-
get length() {
|
|
525
|
+
get length(): number {
|
|
625
526
|
let ptrobj = _getPtr(this);
|
|
626
527
|
let length;
|
|
627
528
|
try {
|
|
628
529
|
length = Module._PyObject_Size(ptrobj);
|
|
629
530
|
} catch (e) {
|
|
630
|
-
|
|
531
|
+
API.fatal_error(e);
|
|
631
532
|
}
|
|
632
533
|
if (length === -1) {
|
|
633
534
|
Module._pythonexc2js();
|
|
@@ -635,35 +536,28 @@ class PyProxyLengthMethods {
|
|
|
635
536
|
return length;
|
|
636
537
|
}
|
|
637
538
|
}
|
|
638
|
-
|
|
639
|
-
/**
|
|
640
|
-
* @typedef {PyProxy & PyProxyGetItemMethods} PyProxyWithGet
|
|
641
|
-
*/
|
|
642
|
-
|
|
539
|
+
export type PyProxyWithGet = PyProxy & PyProxyGetItemMethods;
|
|
643
540
|
// Controlled by HAS_GET, appears for any class with __getitem__,
|
|
644
541
|
// mp_subscript, or sq_item methods
|
|
645
|
-
|
|
646
|
-
* @interface
|
|
647
|
-
*/
|
|
648
|
-
class PyProxyGetItemMethods {
|
|
542
|
+
export class PyProxyGetItemMethods {
|
|
649
543
|
/**
|
|
650
544
|
* This translates to the Python code ``obj[key]``.
|
|
651
545
|
*
|
|
652
546
|
* Present only if the proxied Python object has a ``__getitem__`` method.
|
|
653
547
|
*
|
|
654
|
-
* @param
|
|
655
|
-
* @returns
|
|
548
|
+
* @param key The key to look up.
|
|
549
|
+
* @returns The corresponding value.
|
|
656
550
|
*/
|
|
657
|
-
get(key) {
|
|
551
|
+
get(key: any): any {
|
|
658
552
|
let ptrobj = _getPtr(this);
|
|
659
|
-
let idkey =
|
|
553
|
+
let idkey = Hiwire.new_value(key);
|
|
660
554
|
let idresult;
|
|
661
555
|
try {
|
|
662
556
|
idresult = Module.__pyproxy_getitem(ptrobj, idkey);
|
|
663
557
|
} catch (e) {
|
|
664
|
-
|
|
558
|
+
API.fatal_error(e);
|
|
665
559
|
} finally {
|
|
666
|
-
|
|
560
|
+
Hiwire.decref(idkey);
|
|
667
561
|
}
|
|
668
562
|
if (idresult === 0) {
|
|
669
563
|
if (Module._PyErr_Occurred()) {
|
|
@@ -672,36 +566,33 @@ class PyProxyGetItemMethods {
|
|
|
672
566
|
return undefined;
|
|
673
567
|
}
|
|
674
568
|
}
|
|
675
|
-
return
|
|
569
|
+
return Hiwire.pop_value(idresult);
|
|
676
570
|
}
|
|
677
571
|
}
|
|
678
|
-
|
|
679
|
-
/**
|
|
680
|
-
* @typedef {PyProxy & PyProxySetItemMethods} PyProxyWithSet
|
|
681
|
-
*/
|
|
572
|
+
export type PyProxyWithSet = PyProxy & PyProxySetItemMethods;
|
|
682
573
|
// Controlled by HAS_SET, appears for any class with __setitem__, __delitem__,
|
|
683
574
|
// mp_ass_subscript, or sq_ass_item.
|
|
684
|
-
class PyProxySetItemMethods {
|
|
575
|
+
export class PyProxySetItemMethods {
|
|
685
576
|
/**
|
|
686
577
|
* This translates to the Python code ``obj[key] = value``.
|
|
687
578
|
*
|
|
688
579
|
* Present only if the proxied Python object has a ``__setitem__`` method.
|
|
689
580
|
*
|
|
690
|
-
* @param
|
|
691
|
-
* @param
|
|
581
|
+
* @param key The key to set.
|
|
582
|
+
* @param value The value to set it to.
|
|
692
583
|
*/
|
|
693
|
-
set(key, value) {
|
|
584
|
+
set(key: any, value: any) {
|
|
694
585
|
let ptrobj = _getPtr(this);
|
|
695
|
-
let idkey =
|
|
696
|
-
let idval =
|
|
586
|
+
let idkey = Hiwire.new_value(key);
|
|
587
|
+
let idval = Hiwire.new_value(value);
|
|
697
588
|
let errcode;
|
|
698
589
|
try {
|
|
699
590
|
errcode = Module.__pyproxy_setitem(ptrobj, idkey, idval);
|
|
700
591
|
} catch (e) {
|
|
701
|
-
|
|
592
|
+
API.fatal_error(e);
|
|
702
593
|
} finally {
|
|
703
|
-
|
|
704
|
-
|
|
594
|
+
Hiwire.decref(idkey);
|
|
595
|
+
Hiwire.decref(idval);
|
|
705
596
|
}
|
|
706
597
|
if (errcode === -1) {
|
|
707
598
|
Module._pythonexc2js();
|
|
@@ -712,50 +603,46 @@ class PyProxySetItemMethods {
|
|
|
712
603
|
*
|
|
713
604
|
* Present only if the proxied Python object has a ``__delitem__`` method.
|
|
714
605
|
*
|
|
715
|
-
* @param
|
|
606
|
+
* @param key The key to delete.
|
|
716
607
|
*/
|
|
717
|
-
delete(key) {
|
|
608
|
+
delete(key: any) {
|
|
718
609
|
let ptrobj = _getPtr(this);
|
|
719
|
-
let idkey =
|
|
610
|
+
let idkey = Hiwire.new_value(key);
|
|
720
611
|
let errcode;
|
|
721
612
|
try {
|
|
722
613
|
errcode = Module.__pyproxy_delitem(ptrobj, idkey);
|
|
723
614
|
} catch (e) {
|
|
724
|
-
|
|
615
|
+
API.fatal_error(e);
|
|
725
616
|
} finally {
|
|
726
|
-
|
|
617
|
+
Hiwire.decref(idkey);
|
|
727
618
|
}
|
|
728
619
|
if (errcode === -1) {
|
|
729
620
|
Module._pythonexc2js();
|
|
730
621
|
}
|
|
731
622
|
}
|
|
732
623
|
}
|
|
733
|
-
|
|
734
|
-
/**
|
|
735
|
-
* @typedef {PyProxy & PyProxyContainsMethods} PyProxyWithHas
|
|
736
|
-
*/
|
|
737
|
-
|
|
624
|
+
export type PyProxyWithHas = PyProxy & PyProxyContainsMethods;
|
|
738
625
|
// Controlled by HAS_CONTAINS flag, appears for any class with __contains__ or
|
|
739
626
|
// sq_contains
|
|
740
|
-
class PyProxyContainsMethods {
|
|
627
|
+
export class PyProxyContainsMethods {
|
|
741
628
|
/**
|
|
742
629
|
* This translates to the Python code ``key in obj``.
|
|
743
630
|
*
|
|
744
631
|
* Present only if the proxied Python object has a ``__contains__`` method.
|
|
745
632
|
*
|
|
746
|
-
* @param
|
|
747
|
-
* @returns
|
|
633
|
+
* @param key The key to check for.
|
|
634
|
+
* @returns Is ``key`` present?
|
|
748
635
|
*/
|
|
749
|
-
has(key) {
|
|
636
|
+
has(key: any): boolean {
|
|
750
637
|
let ptrobj = _getPtr(this);
|
|
751
|
-
let idkey =
|
|
638
|
+
let idkey = Hiwire.new_value(key);
|
|
752
639
|
let result;
|
|
753
640
|
try {
|
|
754
641
|
result = Module.__pyproxy_contains(ptrobj, idkey);
|
|
755
642
|
} catch (e) {
|
|
756
|
-
|
|
643
|
+
API.fatal_error(e);
|
|
757
644
|
} finally {
|
|
758
|
-
|
|
645
|
+
Hiwire.decref(idkey);
|
|
759
646
|
}
|
|
760
647
|
if (result === -1) {
|
|
761
648
|
Module._pythonexc2js();
|
|
@@ -763,7 +650,6 @@ class PyProxyContainsMethods {
|
|
|
763
650
|
return result === 1;
|
|
764
651
|
}
|
|
765
652
|
}
|
|
766
|
-
|
|
767
653
|
/**
|
|
768
654
|
* A helper for [Symbol.iterator].
|
|
769
655
|
*
|
|
@@ -780,14 +666,14 @@ class PyProxyContainsMethods {
|
|
|
780
666
|
*
|
|
781
667
|
* @private
|
|
782
668
|
*/
|
|
783
|
-
function* iter_helper(iterptr, token) {
|
|
669
|
+
function* iter_helper(iterptr: number, token: {}): Generator<any> {
|
|
784
670
|
try {
|
|
785
671
|
let item;
|
|
786
672
|
while ((item = Module.__pyproxy_iter_next(iterptr))) {
|
|
787
|
-
yield
|
|
673
|
+
yield Hiwire.pop_value(item);
|
|
788
674
|
}
|
|
789
675
|
} catch (e) {
|
|
790
|
-
|
|
676
|
+
API.fatal_error(e);
|
|
791
677
|
} finally {
|
|
792
678
|
Module.finalizationRegistry.unregister(token);
|
|
793
679
|
Module._Py_DecRef(iterptr);
|
|
@@ -796,16 +682,12 @@ function* iter_helper(iterptr, token) {
|
|
|
796
682
|
Module._pythonexc2js();
|
|
797
683
|
}
|
|
798
684
|
}
|
|
799
|
-
|
|
800
|
-
/**
|
|
801
|
-
* @typedef {PyProxy & PyProxyIterableMethods} PyProxyIterable
|
|
802
|
-
*/
|
|
803
|
-
|
|
685
|
+
export type PyProxyIterable = PyProxy & PyProxyIterableMethods;
|
|
804
686
|
// Controlled by IS_ITERABLE, appears for any object with __iter__ or tp_iter,
|
|
805
687
|
// unless they are iterators. See: https://docs.python.org/3/c-api/iter.html
|
|
806
688
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols
|
|
807
689
|
// This avoids allocating a PyProxy wrapper for the temporary iterator.
|
|
808
|
-
class PyProxyIterableMethods {
|
|
690
|
+
export class PyProxyIterableMethods {
|
|
809
691
|
/**
|
|
810
692
|
* This translates to the Python code ``iter(obj)``. Return an iterator
|
|
811
693
|
* associated to the proxy. See the documentation for `Symbol.iterator
|
|
@@ -815,117 +697,110 @@ class PyProxyIterableMethods {
|
|
|
815
697
|
* ``__iter__`` method).
|
|
816
698
|
*
|
|
817
699
|
* This will be used implicitly by ``for(let x of proxy){}``.
|
|
818
|
-
*
|
|
819
|
-
* @returns {Iterator<Py2JsResult, Py2JsResult, any>} An iterator for the proxied Python object.
|
|
820
700
|
*/
|
|
821
|
-
[Symbol.iterator]() {
|
|
701
|
+
[Symbol.iterator](): Iterator<any, any, any> {
|
|
822
702
|
let ptrobj = _getPtr(this);
|
|
823
703
|
let token = {};
|
|
824
704
|
let iterptr;
|
|
825
705
|
try {
|
|
826
706
|
iterptr = Module._PyObject_GetIter(ptrobj);
|
|
827
707
|
} catch (e) {
|
|
828
|
-
|
|
708
|
+
API.fatal_error(e);
|
|
829
709
|
}
|
|
830
710
|
if (iterptr === 0) {
|
|
831
711
|
Module._pythonexc2js();
|
|
832
712
|
}
|
|
833
|
-
|
|
834
713
|
let result = iter_helper(iterptr, token);
|
|
835
714
|
Module.finalizationRegistry.register(result, [iterptr, undefined], token);
|
|
836
715
|
return result;
|
|
837
716
|
}
|
|
838
717
|
}
|
|
839
|
-
|
|
840
|
-
/**
|
|
841
|
-
* @typedef {PyProxy & PyProxyIteratorMethods} PyProxyIterator
|
|
842
|
-
*/
|
|
843
|
-
|
|
718
|
+
export type PyProxyIterator = PyProxy & PyProxyIteratorMethods;
|
|
844
719
|
// Controlled by IS_ITERATOR, appears for any object with a __next__ or
|
|
845
720
|
// tp_iternext method.
|
|
846
|
-
class PyProxyIteratorMethods {
|
|
721
|
+
export class PyProxyIteratorMethods {
|
|
722
|
+
/** @private */
|
|
847
723
|
[Symbol.iterator]() {
|
|
848
724
|
return this;
|
|
849
725
|
}
|
|
850
726
|
/**
|
|
851
|
-
* This translates to the Python code ``next(obj)``. Returns the next value
|
|
852
|
-
*
|
|
727
|
+
* This translates to the Python code ``next(obj)``. Returns the next value of
|
|
728
|
+
* the generator. See the documentation for `Generator.prototype.next
|
|
853
729
|
* <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/next>`_.
|
|
854
730
|
* The argument will be sent to the Python generator.
|
|
855
731
|
*
|
|
856
732
|
* This will be used implicitly by ``for(let x of proxy){}``.
|
|
857
733
|
*
|
|
858
|
-
* Present only if the proxied Python object is a generator or iterator
|
|
859
|
-
*
|
|
734
|
+
* Present only if the proxied Python object is a generator or iterator (i.e.,
|
|
735
|
+
* has a ``send`` or ``__next__`` method).
|
|
860
736
|
*
|
|
861
|
-
* @param
|
|
862
|
-
*
|
|
863
|
-
* @returns
|
|
864
|
-
*
|
|
865
|
-
*
|
|
866
|
-
*
|
|
867
|
-
* true, value : result_value}``.
|
|
737
|
+
* @param any The value to send to the generator. The value will be assigned
|
|
738
|
+
* as a result of a yield expression.
|
|
739
|
+
* @returns An Object with two properties: ``done`` and ``value``. When the
|
|
740
|
+
* generator yields ``some_value``, ``next`` returns ``{done : false, value :
|
|
741
|
+
* some_value}``. When the generator raises a ``StopIteration(result_value)``
|
|
742
|
+
* exception, ``next`` returns ``{done : true, value : result_value}``.
|
|
868
743
|
*/
|
|
869
|
-
next(arg = undefined) {
|
|
870
|
-
let idresult;
|
|
744
|
+
next(arg: any = undefined): IteratorResult<any, any> {
|
|
871
745
|
// Note: arg is optional, if arg is not supplied, it will be undefined
|
|
872
746
|
// which gets converted to "Py_None". This is as intended.
|
|
873
|
-
let idarg =
|
|
747
|
+
let idarg = Hiwire.new_value(arg);
|
|
748
|
+
let status;
|
|
874
749
|
let done;
|
|
750
|
+
let stackTop = Module.stackSave();
|
|
751
|
+
let res_ptr = Module.stackAlloc(4);
|
|
875
752
|
try {
|
|
876
|
-
|
|
877
|
-
done = idresult === 0;
|
|
878
|
-
if (done) {
|
|
879
|
-
idresult = Module.__pyproxyGen_FetchStopIterationValue();
|
|
880
|
-
}
|
|
753
|
+
status = Module.__pyproxyGen_Send(_getPtr(this), idarg, res_ptr);
|
|
881
754
|
} catch (e) {
|
|
882
|
-
|
|
755
|
+
API.fatal_error(e);
|
|
883
756
|
} finally {
|
|
884
|
-
|
|
757
|
+
Hiwire.decref(idarg);
|
|
885
758
|
}
|
|
886
|
-
|
|
759
|
+
let HEAPU32 = Module.HEAPU32;
|
|
760
|
+
let idresult = HEAPU32[(res_ptr >> 2) + 0];
|
|
761
|
+
Module.stackRestore(stackTop);
|
|
762
|
+
if (status === -1) {
|
|
887
763
|
Module._pythonexc2js();
|
|
888
764
|
}
|
|
889
|
-
let value =
|
|
765
|
+
let value = Hiwire.pop_value(idresult);
|
|
766
|
+
done = status === 0;
|
|
890
767
|
return { done, value };
|
|
891
768
|
}
|
|
892
769
|
}
|
|
893
|
-
|
|
894
770
|
// Another layer of boilerplate. The PyProxyHandlers have some annoying logic
|
|
895
771
|
// to deal with straining out the spurious "Function" properties "prototype",
|
|
896
772
|
// "arguments", and "length", to deal with correctly satisfying the Proxy
|
|
897
773
|
// invariants, and to deal with the mro
|
|
898
|
-
function python_hasattr(jsobj, jskey) {
|
|
774
|
+
function python_hasattr(jsobj: PyProxyClass, jskey: any) {
|
|
899
775
|
let ptrobj = _getPtr(jsobj);
|
|
900
|
-
let idkey =
|
|
776
|
+
let idkey = Hiwire.new_value(jskey);
|
|
901
777
|
let result;
|
|
902
778
|
try {
|
|
903
779
|
result = Module.__pyproxy_hasattr(ptrobj, idkey);
|
|
904
780
|
} catch (e) {
|
|
905
|
-
|
|
781
|
+
API.fatal_error(e);
|
|
906
782
|
} finally {
|
|
907
|
-
|
|
783
|
+
Hiwire.decref(idkey);
|
|
908
784
|
}
|
|
909
785
|
if (result === -1) {
|
|
910
786
|
Module._pythonexc2js();
|
|
911
787
|
}
|
|
912
788
|
return result !== 0;
|
|
913
789
|
}
|
|
914
|
-
|
|
915
790
|
// Returns a JsRef in order to allow us to differentiate between "not found"
|
|
916
791
|
// (in which case we return 0) and "found 'None'" (in which case we return
|
|
917
792
|
// Js_undefined).
|
|
918
|
-
function python_getattr(jsobj, jskey) {
|
|
793
|
+
function python_getattr(jsobj: PyProxyClass, jskey: any) {
|
|
919
794
|
let ptrobj = _getPtr(jsobj);
|
|
920
|
-
let idkey =
|
|
795
|
+
let idkey = Hiwire.new_value(jskey);
|
|
921
796
|
let idresult;
|
|
922
797
|
let cacheId = jsobj.$$.cache.cacheId;
|
|
923
798
|
try {
|
|
924
799
|
idresult = Module.__pyproxy_getattr(ptrobj, idkey, cacheId);
|
|
925
800
|
} catch (e) {
|
|
926
|
-
|
|
801
|
+
API.fatal_error(e);
|
|
927
802
|
} finally {
|
|
928
|
-
|
|
803
|
+
Hiwire.decref(idkey);
|
|
929
804
|
}
|
|
930
805
|
if (idresult === 0) {
|
|
931
806
|
if (Module._PyErr_Occurred()) {
|
|
@@ -934,41 +809,38 @@ function python_getattr(jsobj, jskey) {
|
|
|
934
809
|
}
|
|
935
810
|
return idresult;
|
|
936
811
|
}
|
|
937
|
-
|
|
938
|
-
function python_setattr(jsobj, jskey, jsval) {
|
|
812
|
+
function python_setattr(jsobj: PyProxyClass, jskey: any, jsval: any) {
|
|
939
813
|
let ptrobj = _getPtr(jsobj);
|
|
940
|
-
let idkey =
|
|
941
|
-
let idval =
|
|
814
|
+
let idkey = Hiwire.new_value(jskey);
|
|
815
|
+
let idval = Hiwire.new_value(jsval);
|
|
942
816
|
let errcode;
|
|
943
817
|
try {
|
|
944
818
|
errcode = Module.__pyproxy_setattr(ptrobj, idkey, idval);
|
|
945
819
|
} catch (e) {
|
|
946
|
-
|
|
820
|
+
API.fatal_error(e);
|
|
947
821
|
} finally {
|
|
948
|
-
|
|
949
|
-
|
|
822
|
+
Hiwire.decref(idkey);
|
|
823
|
+
Hiwire.decref(idval);
|
|
950
824
|
}
|
|
951
825
|
if (errcode === -1) {
|
|
952
826
|
Module._pythonexc2js();
|
|
953
827
|
}
|
|
954
828
|
}
|
|
955
|
-
|
|
956
|
-
function python_delattr(jsobj, jskey) {
|
|
829
|
+
function python_delattr(jsobj: PyProxyClass, jskey: any) {
|
|
957
830
|
let ptrobj = _getPtr(jsobj);
|
|
958
|
-
let idkey =
|
|
831
|
+
let idkey = Hiwire.new_value(jskey);
|
|
959
832
|
let errcode;
|
|
960
833
|
try {
|
|
961
834
|
errcode = Module.__pyproxy_delattr(ptrobj, idkey);
|
|
962
835
|
} catch (e) {
|
|
963
|
-
|
|
836
|
+
API.fatal_error(e);
|
|
964
837
|
} finally {
|
|
965
|
-
|
|
838
|
+
Hiwire.decref(idkey);
|
|
966
839
|
}
|
|
967
840
|
if (errcode === -1) {
|
|
968
841
|
Module._pythonexc2js();
|
|
969
842
|
}
|
|
970
843
|
}
|
|
971
|
-
|
|
972
844
|
// See explanation of which methods should be defined here and what they do
|
|
973
845
|
// here:
|
|
974
846
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
|
|
@@ -976,7 +848,7 @@ let PyProxyHandlers = {
|
|
|
976
848
|
isExtensible() {
|
|
977
849
|
return (!!1);
|
|
978
850
|
},
|
|
979
|
-
has(jsobj, jskey) {
|
|
851
|
+
has(jsobj: PyProxyClass, jskey: any) {
|
|
980
852
|
// Note: must report "prototype" in proxy when we are callable.
|
|
981
853
|
// (We can return the wrong value from "get" handler though.)
|
|
982
854
|
let objHasKey = Reflect.has(jsobj, jskey);
|
|
@@ -992,11 +864,10 @@ let PyProxyHandlers = {
|
|
|
992
864
|
}
|
|
993
865
|
return python_hasattr(jsobj, jskey);
|
|
994
866
|
},
|
|
995
|
-
get(jsobj, jskey) {
|
|
867
|
+
get(jsobj: PyProxyClass, jskey: any) {
|
|
996
868
|
// Preference order:
|
|
997
869
|
// 1. stuff from JavaScript
|
|
998
870
|
// 2. the result of Python getattr
|
|
999
|
-
|
|
1000
871
|
// python_getattr will crash if given a Symbol.
|
|
1001
872
|
if (jskey in jsobj || typeof jskey === "symbol") {
|
|
1002
873
|
return Reflect.get(jsobj, jskey);
|
|
@@ -1009,10 +880,10 @@ let PyProxyHandlers = {
|
|
|
1009
880
|
// 2. The result of getattr
|
|
1010
881
|
let idresult = python_getattr(jsobj, jskey);
|
|
1011
882
|
if (idresult !== 0) {
|
|
1012
|
-
return
|
|
883
|
+
return Hiwire.pop_value(idresult);
|
|
1013
884
|
}
|
|
1014
885
|
},
|
|
1015
|
-
set(jsobj, jskey, jsval) {
|
|
886
|
+
set(jsobj: PyProxyClass, jskey: any, jsval: any) {
|
|
1016
887
|
let descr = Object.getOwnPropertyDescriptor(jsobj, jskey);
|
|
1017
888
|
if (descr && !descr.writable) {
|
|
1018
889
|
throw new TypeError(`Cannot set read only field '${jskey}'`);
|
|
@@ -1027,7 +898,7 @@ let PyProxyHandlers = {
|
|
|
1027
898
|
python_setattr(jsobj, jskey, jsval);
|
|
1028
899
|
return (!!1);
|
|
1029
900
|
},
|
|
1030
|
-
deleteProperty(jsobj, jskey) {
|
|
901
|
+
deleteProperty(jsobj: PyProxyClass, jskey: any): boolean {
|
|
1031
902
|
let descr = Object.getOwnPropertyDescriptor(jsobj, jskey);
|
|
1032
903
|
if (descr && !descr.writable) {
|
|
1033
904
|
throw new TypeError(`Cannot delete read only field '${jskey}'`);
|
|
@@ -1041,44 +912,41 @@ let PyProxyHandlers = {
|
|
|
1041
912
|
python_delattr(jsobj, jskey);
|
|
1042
913
|
// Must return "false" if "jskey" is a nonconfigurable own property.
|
|
1043
914
|
// Otherwise JavaScript will throw a TypeError.
|
|
1044
|
-
return !descr || descr.configurable;
|
|
915
|
+
return !descr || !!descr.configurable;
|
|
1045
916
|
},
|
|
1046
|
-
ownKeys(jsobj) {
|
|
917
|
+
ownKeys(jsobj: PyProxyClass) {
|
|
1047
918
|
let ptrobj = _getPtr(jsobj);
|
|
1048
919
|
let idresult;
|
|
1049
920
|
try {
|
|
1050
921
|
idresult = Module.__pyproxy_ownKeys(ptrobj);
|
|
1051
922
|
} catch (e) {
|
|
1052
|
-
|
|
923
|
+
API.fatal_error(e);
|
|
1053
924
|
}
|
|
1054
925
|
if (idresult === 0) {
|
|
1055
926
|
Module._pythonexc2js();
|
|
1056
927
|
}
|
|
1057
|
-
let result =
|
|
928
|
+
let result = Hiwire.pop_value(idresult);
|
|
1058
929
|
result.push(...Reflect.ownKeys(jsobj));
|
|
1059
930
|
return result;
|
|
1060
931
|
},
|
|
1061
|
-
apply(jsobj, jsthis, jsargs) {
|
|
932
|
+
apply(jsobj: PyProxyClass & Function, jsthis: any, jsargs: any) {
|
|
1062
933
|
return jsobj.apply(jsthis, jsargs);
|
|
1063
934
|
},
|
|
1064
935
|
};
|
|
1065
|
-
|
|
1066
|
-
/**
|
|
1067
|
-
* @typedef {PyProxy & Promise<Py2JsResult>} PyProxyAwaitable
|
|
1068
|
-
*/
|
|
1069
|
-
|
|
936
|
+
export type PyProxyAwaitable = PyProxy & Promise<any>;
|
|
1070
937
|
/**
|
|
1071
938
|
* The Promise / JavaScript awaitable API.
|
|
1072
939
|
* @private
|
|
1073
940
|
*/
|
|
1074
|
-
class PyProxyAwaitableMethods {
|
|
941
|
+
export class PyProxyAwaitableMethods {
|
|
942
|
+
$$: any;
|
|
1075
943
|
/**
|
|
1076
944
|
* This wraps __pyproxy_ensure_future and makes a function that converts a
|
|
1077
945
|
* Python awaitable to a promise, scheduling the awaitable on the Python
|
|
1078
946
|
* event loop if necessary.
|
|
1079
947
|
* @private
|
|
1080
948
|
*/
|
|
1081
|
-
_ensure_future() {
|
|
949
|
+
_ensure_future(): Promise<any> {
|
|
1082
950
|
if (this.$$.promise) {
|
|
1083
951
|
return this.$$.promise;
|
|
1084
952
|
}
|
|
@@ -1089,8 +957,8 @@ class PyProxyAwaitableMethods {
|
|
|
1089
957
|
resolveHandle = resolve;
|
|
1090
958
|
rejectHandle = reject;
|
|
1091
959
|
});
|
|
1092
|
-
let resolve_handle_id =
|
|
1093
|
-
let reject_handle_id =
|
|
960
|
+
let resolve_handle_id = Hiwire.new_value(resolveHandle);
|
|
961
|
+
let reject_handle_id = Hiwire.new_value(rejectHandle);
|
|
1094
962
|
let errcode;
|
|
1095
963
|
try {
|
|
1096
964
|
errcode = Module.__pyproxy_ensure_future(
|
|
@@ -1099,15 +967,16 @@ class PyProxyAwaitableMethods {
|
|
|
1099
967
|
reject_handle_id
|
|
1100
968
|
);
|
|
1101
969
|
} catch (e) {
|
|
1102
|
-
|
|
970
|
+
API.fatal_error(e);
|
|
1103
971
|
} finally {
|
|
1104
|
-
|
|
1105
|
-
|
|
972
|
+
Hiwire.decref(reject_handle_id);
|
|
973
|
+
Hiwire.decref(resolve_handle_id);
|
|
1106
974
|
}
|
|
1107
975
|
if (errcode === -1) {
|
|
1108
976
|
Module._pythonexc2js();
|
|
1109
977
|
}
|
|
1110
978
|
this.$$.promise = promise;
|
|
979
|
+
// @ts-ignore
|
|
1111
980
|
this.destroy();
|
|
1112
981
|
return promise;
|
|
1113
982
|
}
|
|
@@ -1115,7 +984,7 @@ class PyProxyAwaitableMethods {
|
|
|
1115
984
|
* Runs ``asyncio.ensure_future(awaitable)``, executes
|
|
1116
985
|
* ``onFulfilled(result)`` when the ``Future`` resolves successfully,
|
|
1117
986
|
* executes ``onRejected(error)`` when the ``Future`` fails. Will be used
|
|
1118
|
-
*
|
|
987
|
+
* implicitly by ``await obj``.
|
|
1119
988
|
*
|
|
1120
989
|
* See the documentation for
|
|
1121
990
|
* `Promise.then
|
|
@@ -1124,13 +993,16 @@ class PyProxyAwaitableMethods {
|
|
|
1124
993
|
* Present only if the proxied Python object is `awaitable
|
|
1125
994
|
* <https://docs.python.org/3/library/asyncio-task.html?highlight=awaitable#awaitables>`_.
|
|
1126
995
|
*
|
|
1127
|
-
* @param
|
|
996
|
+
* @param onFulfilled A handler called with the result as an
|
|
1128
997
|
* argument if the awaitable succeeds.
|
|
1129
|
-
* @param
|
|
998
|
+
* @param onRejected A handler called with the error as an
|
|
1130
999
|
* argument if the awaitable fails.
|
|
1131
|
-
* @returns
|
|
1000
|
+
* @returns The resulting Promise.
|
|
1132
1001
|
*/
|
|
1133
|
-
then(
|
|
1002
|
+
then(
|
|
1003
|
+
onFulfilled: (value: any) => any,
|
|
1004
|
+
onRejected: (reason: any) => any
|
|
1005
|
+
): Promise<any> {
|
|
1134
1006
|
let promise = this._ensure_future();
|
|
1135
1007
|
return promise.then(onFulfilled, onRejected);
|
|
1136
1008
|
}
|
|
@@ -1145,11 +1017,11 @@ class PyProxyAwaitableMethods {
|
|
|
1145
1017
|
* Present only if the proxied Python object is `awaitable
|
|
1146
1018
|
* <https://docs.python.org/3/library/asyncio-task.html?highlight=awaitable#awaitables>`_.
|
|
1147
1019
|
*
|
|
1148
|
-
* @param
|
|
1020
|
+
* @param onRejected A handler called with the error as an
|
|
1149
1021
|
* argument if the awaitable fails.
|
|
1150
|
-
* @returns
|
|
1022
|
+
* @returns The resulting Promise.
|
|
1151
1023
|
*/
|
|
1152
|
-
catch(onRejected) {
|
|
1024
|
+
catch(onRejected: (reason: any) => any) {
|
|
1153
1025
|
let promise = this._ensure_future();
|
|
1154
1026
|
return promise.catch(onRejected);
|
|
1155
1027
|
}
|
|
@@ -1165,33 +1037,32 @@ class PyProxyAwaitableMethods {
|
|
|
1165
1037
|
* <https://docs.python.org/3/library/asyncio-task.html?highlight=awaitable#awaitables>`_.
|
|
1166
1038
|
*
|
|
1167
1039
|
*
|
|
1168
|
-
* @param
|
|
1040
|
+
* @param onFinally A handler that is called with zero arguments
|
|
1169
1041
|
* when the awaitable resolves.
|
|
1170
|
-
* @returns
|
|
1042
|
+
* @returns A Promise that resolves or rejects with the same
|
|
1171
1043
|
* result as the original Promise, but only after executing the
|
|
1172
1044
|
* ``onFinally`` handler.
|
|
1173
1045
|
*/
|
|
1174
|
-
finally(onFinally) {
|
|
1046
|
+
finally(onFinally: () => void) {
|
|
1175
1047
|
let promise = this._ensure_future();
|
|
1176
1048
|
return promise.finally(onFinally);
|
|
1177
1049
|
}
|
|
1178
1050
|
}
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
apply(jsthis, jsargs) {
|
|
1051
|
+
export type PyProxyCallable = PyProxy &
|
|
1052
|
+
PyProxyCallableMethods &
|
|
1053
|
+
((...args: any[]) => any);
|
|
1054
|
+
export class PyProxyCallableMethods {
|
|
1055
|
+
apply(jsthis: PyProxyClass, jsargs: any) {
|
|
1185
1056
|
return Module.callPyObject(_getPtr(this), ...jsargs);
|
|
1186
1057
|
}
|
|
1187
|
-
call(jsthis, ...jsargs) {
|
|
1058
|
+
call(jsthis: PyProxyClass, ...jsargs: any) {
|
|
1188
1059
|
return Module.callPyObject(_getPtr(this), ...jsargs);
|
|
1189
1060
|
}
|
|
1190
1061
|
/**
|
|
1191
1062
|
* Call the function with key word arguments.
|
|
1192
1063
|
* The last argument must be an object with the keyword arguments.
|
|
1193
1064
|
*/
|
|
1194
|
-
callKwargs(...jsargs) {
|
|
1065
|
+
callKwargs(...jsargs: any) {
|
|
1195
1066
|
if (jsargs.length === 0) {
|
|
1196
1067
|
throw new TypeError(
|
|
1197
1068
|
"callKwargs requires at least one argument (the key word argument object)"
|
|
@@ -1207,9 +1078,10 @@ class PyProxyCallableMethods {
|
|
|
1207
1078
|
return Module.callPyObjectKwargs(_getPtr(this), ...jsargs);
|
|
1208
1079
|
}
|
|
1209
1080
|
}
|
|
1081
|
+
// @ts-ignore
|
|
1210
1082
|
PyProxyCallableMethods.prototype.prototype = Function.prototype;
|
|
1211
|
-
|
|
1212
|
-
let type_to_array_map = new Map([
|
|
1083
|
+
// @ts-ignore
|
|
1084
|
+
let type_to_array_map: Map<string, any> = new Map([
|
|
1213
1085
|
["i8", Int8Array],
|
|
1214
1086
|
["u8", Uint8Array],
|
|
1215
1087
|
["u8clamped", Uint8ClampedArray],
|
|
@@ -1227,11 +1099,8 @@ let type_to_array_map = new Map([
|
|
|
1227
1099
|
["f64", Float64Array],
|
|
1228
1100
|
["dataview", DataView],
|
|
1229
1101
|
]);
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
* @typedef {PyProxy & PyProxyBufferMethods} PyProxyBuffer
|
|
1233
|
-
*/
|
|
1234
|
-
class PyProxyBufferMethods {
|
|
1102
|
+
export type PyProxyBuffer = PyProxy & PyProxyBufferMethods;
|
|
1103
|
+
export class PyProxyBufferMethods {
|
|
1235
1104
|
/**
|
|
1236
1105
|
* Get a view of the buffer data which is usable from JavaScript. No copy is
|
|
1237
1106
|
* ever performed.
|
|
@@ -1253,16 +1122,16 @@ class PyProxyBufferMethods {
|
|
|
1253
1122
|
* have support for big endian data, so you might want to pass
|
|
1254
1123
|
* ``'dataview'`` as the type argument in that case.
|
|
1255
1124
|
*
|
|
1256
|
-
* @param
|
|
1125
|
+
* @param type The type of the :any:`PyBuffer.data <pyodide.PyBuffer.data>` field in the
|
|
1257
1126
|
* output. Should be one of: ``"i8"``, ``"u8"``, ``"u8clamped"``, ``"i16"``,
|
|
1258
1127
|
* ``"u16"``, ``"i32"``, ``"u32"``, ``"i32"``, ``"u32"``, ``"i64"``,
|
|
1259
1128
|
* ``"u64"``, ``"f32"``, ``"f64``, or ``"dataview"``. This argument is
|
|
1260
1129
|
* optional, if absent ``getBuffer`` will try to determine the appropriate
|
|
1261
1130
|
* output type based on the buffer `format string
|
|
1262
1131
|
* <https://docs.python.org/3/library/struct.html#format-strings>`_.
|
|
1263
|
-
* @returns
|
|
1132
|
+
* @returns :any:`PyBuffer <pyodide.PyBuffer>`
|
|
1264
1133
|
*/
|
|
1265
|
-
getBuffer(type) {
|
|
1134
|
+
getBuffer(type?: string): PyBuffer {
|
|
1266
1135
|
let ArrayType = undefined;
|
|
1267
1136
|
if (type) {
|
|
1268
1137
|
ArrayType = type_to_array_map.get(type);
|
|
@@ -1280,30 +1149,25 @@ class PyProxyBufferMethods {
|
|
|
1280
1149
|
try {
|
|
1281
1150
|
errcode = Module.__pyproxy_get_buffer(buffer_struct_ptr, this_ptr);
|
|
1282
1151
|
} catch (e) {
|
|
1283
|
-
|
|
1152
|
+
API.fatal_error(e);
|
|
1284
1153
|
}
|
|
1285
1154
|
if (errcode === -1) {
|
|
1286
1155
|
Module._pythonexc2js();
|
|
1287
1156
|
}
|
|
1288
|
-
|
|
1289
1157
|
// This has to match the fields in buffer_struct
|
|
1290
1158
|
let startByteOffset = HEAPU32[(buffer_struct_ptr >> 2) + 0];
|
|
1291
1159
|
let minByteOffset = HEAPU32[(buffer_struct_ptr >> 2) + 1];
|
|
1292
1160
|
let maxByteOffset = HEAPU32[(buffer_struct_ptr >> 2) + 2];
|
|
1293
|
-
|
|
1294
1161
|
let readonly = !!HEAPU32[(buffer_struct_ptr >> 2) + 3];
|
|
1295
1162
|
let format_ptr = HEAPU32[(buffer_struct_ptr >> 2) + 4];
|
|
1296
1163
|
let itemsize = HEAPU32[(buffer_struct_ptr >> 2) + 5];
|
|
1297
|
-
let shape =
|
|
1298
|
-
let strides =
|
|
1299
|
-
|
|
1164
|
+
let shape = Hiwire.pop_value(HEAPU32[(buffer_struct_ptr >> 2) + 6]);
|
|
1165
|
+
let strides = Hiwire.pop_value(HEAPU32[(buffer_struct_ptr >> 2) + 7]);
|
|
1300
1166
|
let view_ptr = HEAPU32[(buffer_struct_ptr >> 2) + 8];
|
|
1301
1167
|
let c_contiguous = !!HEAPU32[(buffer_struct_ptr >> 2) + 9];
|
|
1302
1168
|
let f_contiguous = !!HEAPU32[(buffer_struct_ptr >> 2) + 10];
|
|
1303
|
-
|
|
1304
1169
|
let format = Module.UTF8ToString(format_ptr);
|
|
1305
1170
|
Module.stackRestore(orig_stack_ptr);
|
|
1306
|
-
|
|
1307
1171
|
let success = (!!0);
|
|
1308
1172
|
try {
|
|
1309
1173
|
let bigEndian = (!!0);
|
|
@@ -1346,7 +1210,6 @@ class PyProxyBufferMethods {
|
|
|
1346
1210
|
for (let i of strides.keys()) {
|
|
1347
1211
|
strides[i] /= alignment;
|
|
1348
1212
|
}
|
|
1349
|
-
|
|
1350
1213
|
success = (!!1);
|
|
1351
1214
|
let result = Object.create(
|
|
1352
1215
|
PyBuffer.prototype,
|
|
@@ -1374,17 +1237,23 @@ class PyProxyBufferMethods {
|
|
|
1374
1237
|
Module._PyBuffer_Release(view_ptr);
|
|
1375
1238
|
Module._PyMem_Free(view_ptr);
|
|
1376
1239
|
} catch (e) {
|
|
1377
|
-
|
|
1240
|
+
API.fatal_error(e);
|
|
1378
1241
|
}
|
|
1379
1242
|
}
|
|
1380
1243
|
}
|
|
1381
1244
|
}
|
|
1382
1245
|
}
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1246
|
+
export type TypedArray =
|
|
1247
|
+
| Int8Array
|
|
1248
|
+
| Uint8Array
|
|
1249
|
+
| Int16Array
|
|
1250
|
+
| Uint16Array
|
|
1251
|
+
| Int32Array
|
|
1252
|
+
| Uint32Array
|
|
1253
|
+
| Uint8ClampedArray
|
|
1254
|
+
| Float32Array
|
|
1255
|
+
| Float64Array;
|
|
1256
|
+
export type PyProxyDict = PyProxyWithGet & PyProxyWithSet & PyProxyWithHas;
|
|
1388
1257
|
/**
|
|
1389
1258
|
* A class to allow access to a Python data buffers from JavaScript. These are
|
|
1390
1259
|
* produced by :any:`PyProxy.getBuffer` and cannot be constructed directly.
|
|
@@ -1452,93 +1321,82 @@ class PyProxyBufferMethods {
|
|
|
1452
1321
|
* );
|
|
1453
1322
|
*/
|
|
1454
1323
|
export class PyBuffer {
|
|
1324
|
+
/**
|
|
1325
|
+
* The offset of the first entry of the array. For instance if our array
|
|
1326
|
+
* is 3d, then you will find ``array[0,0,0]`` at
|
|
1327
|
+
* ``pybuf.data[pybuf.offset]``
|
|
1328
|
+
*/
|
|
1329
|
+
offset: number;
|
|
1330
|
+
/**
|
|
1331
|
+
* If the data is readonly, you should not modify it. There is no way
|
|
1332
|
+
* for us to enforce this, but it may cause very weird behavior.
|
|
1333
|
+
*/
|
|
1334
|
+
readonly: boolean;
|
|
1335
|
+
/**
|
|
1336
|
+
* The format string for the buffer. See `the Python documentation on
|
|
1337
|
+
* format strings
|
|
1338
|
+
* <https://docs.python.org/3/library/struct.html#format-strings>`_.
|
|
1339
|
+
*/
|
|
1340
|
+
format: string;
|
|
1341
|
+
/**
|
|
1342
|
+
* How large is each entry (in bytes)?
|
|
1343
|
+
*/
|
|
1344
|
+
itemsize: number;
|
|
1345
|
+
/**
|
|
1346
|
+
* The number of dimensions of the buffer. If ``ndim`` is 0, the buffer
|
|
1347
|
+
* represents a single scalar or struct. Otherwise, it represents an
|
|
1348
|
+
* array.
|
|
1349
|
+
*/
|
|
1350
|
+
ndim: number;
|
|
1351
|
+
/**
|
|
1352
|
+
* The total number of bytes the buffer takes up. This is equal to
|
|
1353
|
+
* ``buff.data.byteLength``.
|
|
1354
|
+
*/
|
|
1355
|
+
nbytes: number;
|
|
1356
|
+
/**
|
|
1357
|
+
* The shape of the buffer, that is how long it is in each dimension.
|
|
1358
|
+
* The length will be equal to ``ndim``. For instance, a 2x3x4 array
|
|
1359
|
+
* would have shape ``[2, 3, 4]``.
|
|
1360
|
+
*/
|
|
1361
|
+
shape: number[];
|
|
1362
|
+
/**
|
|
1363
|
+
* An array of of length ``ndim`` giving the number of elements to skip
|
|
1364
|
+
* to get to a new element in each dimension. See the example definition
|
|
1365
|
+
* of a ``multiIndexToIndex`` function above.
|
|
1366
|
+
*/
|
|
1367
|
+
strides: number[];
|
|
1368
|
+
/**
|
|
1369
|
+
* The actual data. A typed array of an appropriate size backed by a
|
|
1370
|
+
* segment of the WASM memory.
|
|
1371
|
+
*
|
|
1372
|
+
* The ``type`` argument of :any:`PyProxy.getBuffer`
|
|
1373
|
+
* determines which sort of ``TypedArray`` this is. By default
|
|
1374
|
+
* :any:`PyProxy.getBuffer` will look at the format string to determine the most
|
|
1375
|
+
* appropriate option.
|
|
1376
|
+
*/
|
|
1377
|
+
data: TypedArray;
|
|
1378
|
+
/**
|
|
1379
|
+
* Is it C contiguous?
|
|
1380
|
+
*/
|
|
1381
|
+
c_contiguous: boolean;
|
|
1382
|
+
/**
|
|
1383
|
+
* Is it Fortran contiguous?
|
|
1384
|
+
*/
|
|
1385
|
+
f_contiguous: boolean;
|
|
1386
|
+
/**
|
|
1387
|
+
* @private
|
|
1388
|
+
*/
|
|
1389
|
+
_released: boolean;
|
|
1390
|
+
/**
|
|
1391
|
+
* @private
|
|
1392
|
+
*/
|
|
1393
|
+
_view_ptr: number;
|
|
1394
|
+
/**
|
|
1395
|
+
* @private
|
|
1396
|
+
*/
|
|
1455
1397
|
constructor() {
|
|
1456
|
-
/**
|
|
1457
|
-
* The offset of the first entry of the array. For instance if our array
|
|
1458
|
-
* is 3d, then you will find ``array[0,0,0]`` at
|
|
1459
|
-
* ``pybuf.data[pybuf.offset]``
|
|
1460
|
-
* @type {number}
|
|
1461
|
-
*/
|
|
1462
|
-
this.offset;
|
|
1463
|
-
|
|
1464
|
-
/**
|
|
1465
|
-
* If the data is readonly, you should not modify it. There is no way
|
|
1466
|
-
* for us to enforce this, but it may cause very weird behavior.
|
|
1467
|
-
* @type {boolean}
|
|
1468
|
-
*/
|
|
1469
|
-
this.readonly;
|
|
1470
|
-
|
|
1471
|
-
/**
|
|
1472
|
-
* The format string for the buffer. See `the Python documentation on
|
|
1473
|
-
* format strings
|
|
1474
|
-
* <https://docs.python.org/3/library/struct.html#format-strings>`_.
|
|
1475
|
-
* @type {string}
|
|
1476
|
-
*/
|
|
1477
|
-
this.format;
|
|
1478
|
-
|
|
1479
|
-
/**
|
|
1480
|
-
* How large is each entry (in bytes)?
|
|
1481
|
-
* @type {number}
|
|
1482
|
-
*/
|
|
1483
|
-
this.itemsize;
|
|
1484
|
-
|
|
1485
|
-
/**
|
|
1486
|
-
* The number of dimensions of the buffer. If ``ndim`` is 0, the buffer
|
|
1487
|
-
* represents a single scalar or struct. Otherwise, it represents an
|
|
1488
|
-
* array.
|
|
1489
|
-
* @type {number}
|
|
1490
|
-
*/
|
|
1491
|
-
this.ndim;
|
|
1492
|
-
|
|
1493
|
-
/**
|
|
1494
|
-
* The total number of bytes the buffer takes up. This is equal to
|
|
1495
|
-
* ``buff.data.byteLength``.
|
|
1496
|
-
* @type {number}
|
|
1497
|
-
*/
|
|
1498
|
-
this.nbytes;
|
|
1499
|
-
|
|
1500
|
-
/**
|
|
1501
|
-
* The shape of the buffer, that is how long it is in each dimension.
|
|
1502
|
-
* The length will be equal to ``ndim``. For instance, a 2x3x4 array
|
|
1503
|
-
* would have shape ``[2, 3, 4]``.
|
|
1504
|
-
* @type {number[]}
|
|
1505
|
-
*/
|
|
1506
|
-
this.shape;
|
|
1507
|
-
|
|
1508
|
-
/**
|
|
1509
|
-
* An array of of length ``ndim`` giving the number of elements to skip
|
|
1510
|
-
* to get to a new element in each dimension. See the example definition
|
|
1511
|
-
* of a ``multiIndexToIndex`` function above.
|
|
1512
|
-
* @type {number[]}
|
|
1513
|
-
*/
|
|
1514
|
-
this.strides;
|
|
1515
|
-
|
|
1516
|
-
/**
|
|
1517
|
-
* The actual data. A typed array of an appropriate size backed by a
|
|
1518
|
-
* segment of the WASM memory.
|
|
1519
|
-
*
|
|
1520
|
-
* The ``type`` argument of :any:`PyProxy.getBuffer`
|
|
1521
|
-
* determines which sort of ``TypedArray`` this is. By default
|
|
1522
|
-
* :any:`PyProxy.getBuffer` will look at the format string to determine the most
|
|
1523
|
-
* appropriate option.
|
|
1524
|
-
* @type {TypedArray}
|
|
1525
|
-
*/
|
|
1526
|
-
this.data;
|
|
1527
|
-
|
|
1528
|
-
/**
|
|
1529
|
-
* Is it C contiguous?
|
|
1530
|
-
* @type {boolean}
|
|
1531
|
-
*/
|
|
1532
|
-
this.c_contiguous;
|
|
1533
|
-
|
|
1534
|
-
/**
|
|
1535
|
-
* Is it Fortran contiguous?
|
|
1536
|
-
* @type {boolean}
|
|
1537
|
-
*/
|
|
1538
|
-
this.f_contiguous;
|
|
1539
1398
|
throw new TypeError("PyBuffer is not a constructor");
|
|
1540
1399
|
}
|
|
1541
|
-
|
|
1542
1400
|
/**
|
|
1543
1401
|
* Release the buffer. This allows the memory to be reclaimed.
|
|
1544
1402
|
*/
|
|
@@ -1551,9 +1409,10 @@ export class PyBuffer {
|
|
|
1551
1409
|
Module._PyBuffer_Release(this._view_ptr);
|
|
1552
1410
|
Module._PyMem_Free(this._view_ptr);
|
|
1553
1411
|
} catch (e) {
|
|
1554
|
-
|
|
1412
|
+
API.fatal_error(e);
|
|
1555
1413
|
}
|
|
1556
1414
|
this._released = (!!1);
|
|
1415
|
+
// @ts-ignore
|
|
1557
1416
|
this.data = null;
|
|
1558
1417
|
}
|
|
1559
1418
|
}
|