@@ -34,10 +34,12 @@ cdef extern from "emscripten.h":
34
34
void emscripten_async_call(em_arg_callback_func func, void * arg, int millis)
35
35
36
36
void emscripten_sleep(unsigned int ms)
37
- void emscripten_sleep_with_yield(unsigned int ms)
38
37
void emscripten_wget(const char * url, const char * file )
39
38
void emscripten_wget_data(const char * url, void ** pbuffer, int * pnum, int * perror)
40
39
40
+ # Emterpreter-only
41
+ # void emscripten_sleep_with_yield(unsigned int ms)
42
+
41
43
enum :
42
44
EM_LOG_CONSOLE
43
45
EM_LOG_WARN
@@ -53,75 +55,6 @@ cdef extern from "emscripten.h":
53
55
void emscripten_log(int flags, ...)
54
56
int emscripten_get_callstack(int flags, char * out, int maxbytes)
55
57
56
- cdef extern from " emscripten/html5.h" :
57
- ctypedef int EM_BOOL
58
- ctypedef int EMSCRIPTEN_RESULT
59
- enum : EM_TRUE
60
- enum : EM_FALSE
61
-
62
- from libc.stdint cimport uint32_t, uint64_t
63
-
64
- cdef extern from " emscripten/fetch.h" :
65
- ctypedef struct emscripten_fetch_attr_t:
66
- char requestMethod[32 ]
67
- void * userData
68
- void (* onsuccess)(emscripten_fetch_t * fetch)
69
- void (* onerror)(emscripten_fetch_t * fetch)
70
- void (* onprogress)(emscripten_fetch_t * fetch)
71
- void (* onreadystatechange)(emscripten_fetch_t * fetch)
72
- uint32_t attributes
73
- unsigned long timeoutMSecs
74
- EM_BOOL withCredentials
75
- const char * destinationPath
76
- const char * userName
77
- const char * password
78
- const char * const * requestHeaders
79
- const char * overriddenMimeType
80
- const char * requestData
81
- size_t requestDataSize
82
-
83
- ctypedef struct emscripten_fetch_t:
84
- unsigned int id
85
- void * userData
86
- const char * url
87
- const char * data
88
- uint64_t numBytes
89
- uint64_t dataOffset
90
- uint64_t totalBytes
91
- unsigned short readyState
92
- unsigned short status
93
- char statusText[64 ]
94
- uint32_t __proxyState
95
- emscripten_fetch_attr_t __attributes
96
-
97
- enum :
98
- EMSCRIPTEN_FETCH_LOAD_TO_MEMORY
99
- EMSCRIPTEN_FETCH_STREAM_DATA
100
- EMSCRIPTEN_FETCH_PERSIST_FILE
101
- EMSCRIPTEN_FETCH_APPEND
102
- EMSCRIPTEN_FETCH_REPLACE
103
- EMSCRIPTEN_FETCH_NO_DOWNLOAD
104
- EMSCRIPTEN_FETCH_SYNCHRONOUS
105
- EMSCRIPTEN_FETCH_WAITABLE
106
-
107
- void emscripten_fetch_attr_init(emscripten_fetch_attr_t * fetch_attr)
108
- emscripten_fetch_t * emscripten_fetch(emscripten_fetch_attr_t * fetch_attr, const char * url)
109
- # EMSCRIPTEN_RESULT emscripten_fetch_wait(emscripten_fetch_t *fetch, double timeoutMSecs)
110
- EMSCRIPTEN_RESULT emscripten_fetch_close(emscripten_fetch_t * fetch)
111
- size_t emscripten_fetch_get_response_headers_length(emscripten_fetch_t * fetch)
112
- size_t emscripten_fetch_get_response_headers(emscripten_fetch_t * fetch, char * dst, size_t dstSizeBytes)
113
- char ** emscripten_fetch_unpack_response_headers(const char * headersString)
114
- void emscripten_fetch_free_unpacked_response_headers(char ** unpackedHeaders)
115
-
116
- FETCH_LOAD_TO_MEMORY = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY
117
- FETCH_STREAM_DATA = EMSCRIPTEN_FETCH_STREAM_DATA
118
- FETCH_PERSIST_FILE = EMSCRIPTEN_FETCH_PERSIST_FILE
119
- FETCH_APPEND = EMSCRIPTEN_FETCH_APPEND
120
- FETCH_REPLACE = EMSCRIPTEN_FETCH_REPLACE
121
- FETCH_NO_DOWNLOAD = EMSCRIPTEN_FETCH_NO_DOWNLOAD
122
- FETCH_SYNCHRONOUS = EMSCRIPTEN_FETCH_SYNCHRONOUS
123
- FETCH_WAITABLE = EMSCRIPTEN_FETCH_WAITABLE
124
-
125
58
LOG_CONSOLE = EM_LOG_CONSOLE
126
59
LOG_WARN = EM_LOG_WARN
127
60
LOG_ERROR = EM_LOG_ERROR
@@ -140,8 +73,6 @@ from cpython.ref cimport PyObject, Py_XINCREF, Py_XDECREF
140
73
141
74
from cpython.buffer cimport PyBuffer_FillInfo
142
75
143
- from libc.string cimport strncpy
144
-
145
76
# cdef extern from "stdio.h":
146
77
# int puts(const char *s);
147
78
@@ -242,8 +173,9 @@ def exit_with_live_runtime():
242
173
def sleep (ms ):
243
174
emscripten_sleep(ms)
244
175
245
- def sleep_with_yield (ms ):
246
- emscripten_sleep_with_yield(ms)
176
+ # Emterpreter-only
177
+ # def sleep_with_yield(ms):
178
+ # emscripten_sleep_with_yield(ms)
247
179
248
180
def run_script (script ):
249
181
emscripten_run_script(script.encode(' UTF-8' ));
@@ -302,248 +234,6 @@ def async_wget_data(url, arg, onload, onerror=None):
302
234
# emscripten.async_wget_data('https://bank.confidential/', None, None)
303
235
304
236
305
-
306
- # Fetch API
307
- # https://emscripten.org/docs/api_reference/fetch.html
308
-
309
- # http://docs.cython.org/en/latest/src/userguide/extension_types.html
310
- cdef class Fetch:
311
- cdef emscripten_fetch_t * fetch
312
- cdef callbacks
313
-
314
- def __cinit__ (self , url , requestMethod = None , userData = None ,
315
- onsuccess = None , onerror = None , onprogress = None , onreadystatechange = None ,
316
- attributes = None , timeoutMSecs = None , withCredentials = None ,
317
- destinationPath = None , userName = None , password = None ,
318
- requestHeaders = None , overriddenMimeType = None , requestData = None ):
319
-
320
- # Keep track of temporary Python strings we pass emscripten_fetch() for copy
321
- py_str_refs = []
322
-
323
- cdef emscripten_fetch_attr_t attr
324
- emscripten_fetch_attr_init(& attr)
325
-
326
- Py_XINCREF(< PyObject* > self ) # survive until callback
327
- attr.userData = < PyObject* > self
328
-
329
- if requestMethod is not None :
330
- strncpy(attr.requestMethod,
331
- requestMethod.encode(' UTF-8' ),
332
- sizeof(attr.requestMethod) - 1 )
333
-
334
- self .userData = userData
335
-
336
- self .callbacks = {}
337
- attr.onsuccess = callpyfunc_fetch_onsuccess
338
- attr.onerror = callpyfunc_fetch_onerror
339
- if onsuccess is not None :
340
- self .callbacks[' onsuccess' ] = onsuccess
341
- if onerror is not None :
342
- self .callbacks[' onerror' ] = onerror
343
- if onprogress is not None :
344
- self .callbacks[' onprogress' ] = onprogress
345
- attr.onprogress = callpyfunc_fetch_onprogress
346
- if onreadystatechange is not None :
347
- self .callbacks[' onreadystatechange' ] = onreadystatechange
348
- attr.onreadystatechange = callpyfunc_fetch_onreadystatechange
349
-
350
- if attributes is not None :
351
- attr.attributes = attributes
352
- if timeoutMSecs is not None :
353
- attr.timeoutMSecs = timeoutMSecs
354
- if withCredentials is not None :
355
- attr.withCredentials = withCredentials
356
- if destinationPath is not None :
357
- py_str_refs.append(destinationPath.encode(' UTF-8' ))
358
- attr.destinationPath = py_str_refs[- 1 ]
359
- if userName is not None :
360
- py_str_refs.append(userName.encode(' UTF-8' ))
361
- attr.userName = py_str_refs[- 1 ]
362
- if password is not None :
363
- py_str_refs.append(password.encode(' UTF-8' ))
364
- attr.password = py_str_refs[- 1 ]
365
-
366
- cdef char ** headers
367
- if requestHeaders is not None :
368
- size = (2 * len (requestHeaders) + 1 ) * sizeof(char * )
369
- headers = < char ** > PyMem_Malloc(size)
370
- i = 0
371
- for name,value in requestHeaders.items():
372
- py_str_refs.append(name.encode(' UTF-8' ))
373
- headers[i] = py_str_refs[- 1 ]
374
- i += 1
375
- py_str_refs.append(value.encode(' UTF-8' ))
376
- headers[i] = py_str_refs[- 1 ]
377
- i += 1
378
- headers[i] = NULL
379
- attr.requestHeaders = < const char * const * > headers
380
-
381
- if overriddenMimeType is not None :
382
- py_str_refs.append(overriddenMimeType.encode(' UTF-8' ))
383
- attr.overriddenMimeType = py_str_refs[- 1 ]
384
-
385
- if requestData is not None :
386
- size = len (requestData)
387
- attr.requestDataSize = size
388
- # direct pointer, no UTF-8 encoding pass:
389
- attr.requestData = requestData
390
-
391
- # Fetch
392
- cdef emscripten_fetch_t * fetch = emscripten_fetch(& attr, url.encode(' UTF-8' ))
393
- self .fetch = fetch
394
-
395
- # Explicitely deref temporary Python strings. Test for forgotten refs with e.g.:
396
- # print(attr.overriddenMimeType, attr.destinationPath, attr.userName, attr.password)
397
- del py_str_refs
398
-
399
- if requestHeaders is not None :
400
- PyMem_Free(< void * > attr.requestHeaders)
401
-
402
- def __dealloc__ (self ):
403
- emscripten_fetch_close(self .fetch)
404
-
405
- # Currently unsafe:
406
- # https://github.com/emscripten-core/emscripten/issues/8234
407
- # def fetch_close(fetch):
408
- # pass
409
-
410
- # http://docs.cython.org/en/latest/src/userguide/buffer.html
411
- # https://docs.python.org/3/c-api/typeobj.html#c.PyBufferProcs.bf_getbuffer
412
- # https://docs.python.org/3/c-api/buffer.html#c.PyObject_GetBuffer
413
- # https://docs.python.org/3/c-api/buffer.html#c.PyBuffer_FillInfo
414
- def __getbuffer__ (self , Py_buffer *view , int flags ):
415
- if self .fetch.data != NULL :
416
- is_readonly = 1
417
- PyBuffer_FillInfo(view, self , < void * > self .fetch.data, self .fetch.numBytes, is_readonly, flags)
418
- else :
419
- view.obj = None
420
- raise BufferError
421
- def __releasebuffer__ (self , Py_buffer *view ):
422
- pass
423
-
424
- def __repr__ (self ):
425
- return u ' <Fetch: id={}, userData={}, url={}, data={}, dataOffset={}, totalBytes={}, readyState={}, status={}, statusText={}>' .format(repr (self .id), repr (self .userData), repr (self .url), repr (self .data), repr (self .dataOffset), repr (self .totalBytes), repr (self .readyState), repr (self .status), repr (self .statusText))
426
-
427
- # For testing whether a copy occurred:
428
- # def overwrite(self):
429
- # cdef char* overwrite = <char*>(self.fetch.data)
430
- # overwrite[0] = b'O'
431
-
432
- def get_response_headers (self ):
433
- cdef char * buf = NULL
434
- # Note: JS crash if applied on a persisted request from IDB cache
435
- # https://github.com/emscripten-core/emscripten/issues/7026#issuecomment-545488132
436
- cdef length = emscripten_fetch_get_response_headers_length(self .fetch)
437
- if length > 0 :
438
- headersString = < char * > PyMem_Malloc(length)
439
- emscripten_fetch_get_response_headers(self .fetch, headersString, length+ 1 )
440
- ret = headersString[:length] # copy
441
- PyMem_Free(headersString)
442
- return ret
443
- else :
444
- return None
445
-
446
- def get_unpacked_response_headers (self ):
447
- cdef char * headersString = NULL
448
- cdef char ** unpackedHeaders = NULL
449
- # Note: JS crash if applied on a persisted request from IDB cache
450
- cdef length = emscripten_fetch_get_response_headers_length(self .fetch)
451
- if length > 0 :
452
- headersString = < char * > PyMem_Malloc(length)
453
- emscripten_fetch_get_response_headers(self .fetch, headersString, length+ 1 )
454
- unpackedHeaders = emscripten_fetch_unpack_response_headers(headersString)
455
- PyMem_Free(headersString)
456
- d = {}
457
- i = 0
458
- while unpackedHeaders[i] != NULL :
459
- k = unpackedHeaders[i] # c_string_encoding
460
- i += 1
461
- v = unpackedHeaders[i] # c_string_encoding
462
- i += 1
463
- d[k] = v
464
- emscripten_fetch_free_unpacked_response_headers(unpackedHeaders)
465
- return d
466
- else :
467
- return None
468
-
469
- @property
470
- def id (self ):
471
- return self .fetch.id
472
- cdef readonly userData
473
- @property
474
- def url (self ):
475
- # return self.fetch.url.decode('UTF-8')
476
- return self .fetch.url # c_string_encoding
477
- @property
478
- def data (self ):
479
- if self .fetch.data != NULL :
480
- return self
481
- else :
482
- return None
483
- @property
484
- def numBytes (self ):
485
- return self .fetch.numBytes
486
- @property
487
- def dataOffset (self ):
488
- return self .fetch.dataOffset
489
- @property
490
- def totalBytes (self ):
491
- return self .fetch.totalBytes # Content-Length
492
- @property
493
- def readyState (self ):
494
- return self .fetch.readyState
495
- @property
496
- def status (self ):
497
- return self .fetch.status
498
- @property
499
- def statusText (self ):
500
- # return self.fetch.statusText.decode('UTF-8')
501
- return self .fetch.statusText # c_string_encoding
502
-
503
- cdef void callpyfunc_fetch_callback(emscripten_fetch_t * fetch, char * callback_name):
504
- cdef Fetch py_fetch = < Fetch> fetch.userData
505
- # for theoretical concurrency, if we're called during emscripten_fetch()
506
- py_fetch.fetch = fetch
507
- # call Python function
508
- if py_fetch.callbacks.get(callback_name, None ):
509
- py_fetch.callbacks[callback_name](py_fetch)
510
-
511
- # one of {onsuccess,onerror} is guaranteed to run, deref Fetch there
512
- cdef void callpyfunc_fetch_onsuccess(emscripten_fetch_t * fetch):
513
- callpyfunc_fetch_callback(fetch, ' onsuccess' )
514
- Py_XDECREF(< PyObject* > fetch.userData)
515
- cdef void callpyfunc_fetch_onerror(emscripten_fetch_t * fetch):
516
- callpyfunc_fetch_callback(fetch, ' onerror' )
517
- Py_XDECREF(< PyObject* > fetch.userData)
518
- cdef void callpyfunc_fetch_onprogress(emscripten_fetch_t * fetch):
519
- callpyfunc_fetch_callback(fetch, ' onprogress' )
520
- cdef void callpyfunc_fetch_onreadystatechange(emscripten_fetch_t * fetch):
521
- callpyfunc_fetch_callback(fetch, ' onreadystatechange' )
522
-
523
-
524
- # import emscripten,sys; f=lambda x:sys.stdout.write(repr(x)+"\n");
525
- # #Module.cwrap('PyRun_SimpleString', 'number', ['string'])("def g(x):\n global a; a=x")
526
- # emscripten.Fetch('/', onsuccess=f)
527
- # emscripten.Fetch(u'/helloé', onsuccess=f)
528
- # emscripten.Fetch('/hello', attributes=emscripten.FETCH_LOAD_TO_MEMORY, onsuccess=f); del f # output
529
- # fetch_attr={'onsuccess':f}; emscripten.Fetch('/hello', **fetch_attr); del fetch_attr['onsuccess'] # output
530
- # emscripten.Fetch('/non-existent', onerror=lambda x:sys.stdout.write(repr(x)+"\n"))
531
- # emscripten.Fetch('https://bank.confidential/', onerror=lambda x:sys.stdout.write(repr(x)+"\n")) # simulated 404
532
- # emscripten.Fetch('/hello', attributes=emscripten.FETCH_LOAD_TO_MEMORY|emscripten.FETCH_PERSIST_FILE, onsuccess=f)
533
- # Note: fe.fetch.id changes (in-place) when first caching
534
- # emscripten.Fetch('/hello', requestMethod='EM_IDB_DELETE', onsuccess=f)
535
- # emscripten.Fetch('/hello', attributes=emscripten.FETCH_LOAD_TO_MEMORY, requestMethod='POST', requestData='AA\xffBB\x00CC', onsuccess=f, onerror=f)
536
- # emscripten.Fetch('/hello', attributes=emscripten.FETCH_LOAD_TO_MEMORY, requestMethod='12345678901234567890123456789012', onerror=f)
537
- # emscripten.Fetch('/hello', attributes=emscripten.FETCH_LOAD_TO_MEMORY, onsuccess=f, userData='userData', overriddenMimeType='text/html', userName='userName', password='password', requestHeaders={'Content-Type':'text/plain','Cache-Control':'no-store'})
538
- # emscripten.Fetch('/hello', attributes=emscripten.FETCH_LOAD_TO_MEMORY|emscripten.FETCH_PERSIST_FILE, onsuccess=f, destinationPath='destinationPath'); emscripten.Fetch('destinationPath', requestMethod='EM_IDB_DELETE', onsuccess=f)
539
- # fe=emscripten.Fetch('/hello', attributes=emscripten.FETCH_LOAD_TO_MEMORY|emscripten.FETCH_PERSIST_FILE, onsuccess=f, destinationPath='destinationPath'); fe2=emscripten.Fetch('destinationPath', requestMethod='EM_IDB_DELETE', onsuccess=f); print("fe=",fe); print("fe2=",fe2)
540
- # Note: fe2 can occur before fe1
541
- # r=emscripten.Fetch('/hello', attributes=emscripten.FETCH_LOAD_TO_MEMORY)
542
- # open('test.txt','wb').write(r); open('test.txt','rb').read()
543
- # r.data != None
544
- # memoryview(r)[:5].tobytes()
545
- # import cStringIO; cStringIO.StringIO(r).read(5)
546
-
547
237
# requires -s RETAIN_COMPILER_SETTINGS=1 (otherwise Exception)
548
238
def get_compiler_setting (name ):
549
239
cdef void * amb = < void * > emscripten_get_compiler_setting(name.encode(' UTF-8' ))
0 commit comments