8
8
https://emscripten.org/docs/porting/connecting_cpp_and_javascript/WebIDL-Binder.html
9
9
"""
10
10
11
+ import argparse
11
12
import os
12
13
import sys
13
14
from typing import List
@@ -55,8 +56,15 @@ def getExtendedAttribute(self, _name):
55
56
return None
56
57
57
58
58
- input_file = sys .argv [1 ]
59
- output_base = sys .argv [2 ]
59
+ parser = argparse .ArgumentParser ()
60
+ parser .add_argument ('--wasm64' , action = 'store_true' , default = False ,
61
+ help = 'Build for wasm64' )
62
+ parser .add_argument ('infile' )
63
+ parser .add_argument ('outfile' )
64
+ options = parser .parse_args ()
65
+
66
+ input_file = options .infile
67
+ output_base = options .outfile
60
68
cpp_output = output_base + '.cpp'
61
69
js_output = output_base + '.js'
62
70
@@ -89,7 +97,7 @@ def getExtendedAttribute(self, _name):
89
97
#include <emscripten.h>
90
98
#include <stdlib.h>
91
99
92
- EM_JS_DEPS(webidl_binder, "$intArrayFromString,$UTF8ToString");
100
+ EM_JS_DEPS(webidl_binder, "$intArrayFromString,$UTF8ToString,$alignMemory ");
93
101
''' ]
94
102
95
103
mid_c = ['''
@@ -214,7 +222,7 @@ def build_constructor(name):
214
222
assert(ensureCache.buffer);
215
223
var bytes = view.BYTES_PER_ELEMENT;
216
224
var len = array.length * bytes;
217
- len = (len + 7) & -8 ; // keep things aligned to 8 byte boundaries
225
+ len = alignMemory (len, 8) ; // keep things aligned to 8 byte boundaries
218
226
var ret;
219
227
if (ensureCache.pos + len >= ensureCache.size) {
220
228
// we failed to allocate in the buffer, ensureCache time around :(
@@ -230,13 +238,7 @@ def build_constructor(name):
230
238
return ret;
231
239
},
232
240
copy(array, view, offset) {
233
- offset >>>= 0;
234
- var bytes = view.BYTES_PER_ELEMENT;
235
- switch (bytes) {
236
- case 2: offset >>>= 1; break;
237
- case 4: offset >>>= 2; break;
238
- case 8: offset >>>= 3; break;
239
- }
241
+ offset /= view.BYTES_PER_ELEMENT;
240
242
for (var i = 0; i < array.length; i++) {
241
243
view[offset + i] = array[i];
242
244
}
@@ -415,6 +417,11 @@ def render_function(class_name, func_name, sigs, return_type, non_pointer,
415
417
call_postfix = ''
416
418
if return_type != 'Void' and not constructor :
417
419
call_prefix = 'return '
420
+
421
+ ptr_rtn = constructor or return_type in interfaces or return_type == 'String'
422
+ if options .wasm64 and ptr_rtn :
423
+ call_postfix += ')'
424
+
418
425
if not constructor :
419
426
if return_type in interfaces :
420
427
call_prefix += 'wrapPointer('
@@ -426,17 +433,27 @@ def render_function(class_name, func_name, sigs, return_type, non_pointer,
426
433
call_prefix += '!!('
427
434
call_postfix += ')'
428
435
436
+ if options .wasm64 and ptr_rtn :
437
+ call_prefix += 'Number('
438
+
429
439
args = [(all_args [i ].identifier .name if isinstance (all_args [i ], WebIDL .IDLArgument ) else ('arg%d' % i )) for i in range (max_args )]
430
440
if not constructor and not is_static :
431
441
body = ' var self = this.ptr;\n '
432
- pre_arg = ['self' ]
442
+ if options .wasm64 :
443
+ pre_arg = ['BigInt(self)' ]
444
+ else :
445
+ pre_arg = ['self' ]
433
446
else :
434
447
body = ''
435
448
pre_arg = []
436
449
437
450
if any (arg .type .isString () or arg .type .isArray () for arg in all_args ):
438
451
body += ' ensureCache.prepare();\n '
439
452
453
+ def is_ptr_arg (i ):
454
+ t = all_args [i ].type
455
+ return (t .isArray () or t .isAny () or t .isString () or t .isObject () or t .isInterface ())
456
+
440
457
for i , (js_arg , arg ) in enumerate (zip (args , all_args )):
441
458
if i >= min_args :
442
459
optional = True
@@ -500,9 +517,11 @@ def render_function(class_name, func_name, sigs, return_type, non_pointer,
500
517
501
518
if do_default :
502
519
if not (arg .type .isArray () and not array_attribute ):
503
- body += " if ({0 } && typeof {0 } === 'object') {0 } = {0 }.ptr;\n " . format ( js_arg )
520
+ body += f " if ({ js_arg } && typeof { js_arg } === 'object') { js_arg } = { js_arg } .ptr;\n "
504
521
if arg .type .isString ():
505
522
body += " else {0} = ensureString({0});\n " .format (js_arg )
523
+ if options .wasm64 and is_ptr_arg (i ):
524
+ body += f' if ({ args [i ]} === null) { args [i ]} = 0;\n '
506
525
else :
507
526
# an array can be received here
508
527
arg_type = arg .type .name
@@ -517,18 +536,45 @@ def render_function(class_name, func_name, sigs, return_type, non_pointer,
517
536
elif arg_type == 'Double' :
518
537
body += " if (typeof {0} == 'object') {{ {0} = ensureFloat64({0}); }}\n " .format (js_arg )
519
538
539
+ call_args = pre_arg
540
+
541
+ for i , arg in enumerate (args ):
542
+ if options .wasm64 and is_ptr_arg (i ):
543
+ arg = f'BigInt({ arg } )'
544
+ call_args .append (arg )
545
+
520
546
c_names = {}
547
+
548
+ def make_call_args (i ):
549
+ if pre_arg :
550
+ i += 1
551
+ return ', ' .join (call_args [:i ])
552
+
521
553
for i in range (min_args , max_args ):
522
- c_names [i ] = 'emscripten_bind_%s_%d' % (bindings_name , i )
523
- body += ' if (%s === undefined) { %s%s(%s)%s%s }\n ' % (args [i ], call_prefix , '_' + c_names [i ], ', ' .join (pre_arg + args [:i ]), call_postfix , '' if 'return ' in call_prefix else '; ' + (cache or ' ' ) + 'return' )
524
- c_names [max_args ] = 'emscripten_bind_%s_%d' % (bindings_name , max_args )
525
- body += ' %s%s(%s)%s;\n ' % (call_prefix , '_' + c_names [max_args ], ', ' .join (pre_arg + args ), call_postfix )
554
+ c_names [i ] = f'emscripten_bind_{ bindings_name } _{ i } '
555
+ if 'return ' in call_prefix :
556
+ after_call = ''
557
+ else :
558
+ after_call = '; ' + cache + 'return'
559
+ args_for_call = make_call_args (i )
560
+ body += ' if (%s === undefined) { %s_%s(%s)%s%s }\n ' % (args [i ], call_prefix , c_names [i ],
561
+ args_for_call ,
562
+ call_postfix , after_call )
563
+ dbg (call_prefix )
564
+ c_names [max_args ] = f'emscripten_bind_{ bindings_name } _{ max_args } '
565
+ args_for_call = make_call_args (len (args ))
566
+ body += ' %s_%s(%s)%s;\n ' % (call_prefix , c_names [max_args ], args_for_call , call_postfix )
526
567
if cache :
527
- body += ' ' + cache + '\n '
568
+ body += f' { cache } \n '
569
+
570
+ if constructor :
571
+ declare_name = ' ' + func_name
572
+ else :
573
+ declare_name = ''
528
574
mid_js .append (r'''function%s(%s) {
529
575
%s
530
576
};
531
- ''' % (( ' ' + func_name ) if constructor else '' , ', ' .join (args ), body [:- 1 ]))
577
+ ''' % (declare_name , ', ' .join (args ), body [:- 1 ]))
532
578
533
579
# C
534
580
@@ -538,7 +584,8 @@ def render_function(class_name, func_name, sigs, return_type, non_pointer,
538
584
continue
539
585
sig = list (map (full_typename , raw ))
540
586
if array_attribute :
541
- sig = [x .replace ('[]' , '' ) for x in sig ] # for arrays, ignore that this is an array - our get/set methods operate on the elements
587
+ # for arrays, ignore that this is an array - our get/set methods operate on the elements
588
+ sig = [x .replace ('[]' , '' ) for x in sig ]
542
589
543
590
c_arg_types = list (map (type_to_c , sig ))
544
591
c_class_name = type_to_c (class_name , non_pointing = True )
0 commit comments