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
32
33
# DEBUG=1 will print debug info in render_function
33
34
DEBUG = os .environ .get ('IDL_VERBOSE' ) == '1'
34
35
35
- if DEBUG :
36
- print (f'Debug print ON, CHECKS=${ CHECKS } ' )
36
+ def dbg (* args ):
37
+ if DEBUG :
38
+ print (* args , file = sys .stderr )
39
+
40
+ dbg (f'Debug print ON, CHECKS=${ CHECKS } ' )
37
41
38
42
# We need to avoid some closure errors on the constructors we define here.
39
43
CONSTRUCTOR_CLOSURE_SUPPRESSIONS = '/** @suppress {undefinedVars, duplicate} @this{Object} */'
40
44
41
45
42
46
class Dummy :
43
- def __init__ (self , init ):
44
- for k , v in init .items ():
45
- self .__dict__ [k ] = v
47
+ def __init__ (self , type ):
48
+ self .type = type
49
+
50
+ def __repr__ (self ):
51
+ return f'<Dummy type:{ self .type } >'
46
52
47
53
def getExtendedAttribute (self , _name ):
48
54
return None
49
55
50
56
51
- input_file = sys .argv [1 ]
52
- output_base = sys .argv [2 ]
57
+ parser = argparse .ArgumentParser ()
58
+ parser .add_argument ('--wasm64' , action = 'store_true' , default = False ,
59
+ help = 'Build for wasm64' )
60
+ parser .add_argument ('infile' )
61
+ parser .add_argument ('outfile' )
62
+ options = parser .parse_args ()
63
+
64
+ input_file = options .infile
65
+ output_base = options .outfile
53
66
cpp_output = output_base + '.cpp'
54
67
js_output = output_base + '.js'
55
68
@@ -392,13 +405,12 @@ def render_function(class_name, func_name, sigs, return_type, non_pointer,
392
405
all_args = sigs .get (max_args )
393
406
394
407
if DEBUG :
395
- print ('renderfunc' , class_name , func_name , list (sigs .keys ()), return_type , constructor )
396
- for i in range (max_args ):
397
- a = all_args [i ]
408
+ dbg ('renderfunc' , class_name , func_name , list (sigs .keys ()), return_type , constructor )
409
+ for i , a in enumerate (all_args ):
398
410
if isinstance (a , WebIDL .IDLArgument ):
399
- print ( ' ' , a .identifier .name , a .identifier , a .type , a .optional )
411
+ dbg ( ' ' , a .identifier .name , a .identifier , a .type , a .optional )
400
412
else :
401
- print (' arg%d' % i )
413
+ dbg (' arg%d (%s) ' % ( i , a ) )
402
414
403
415
# JS
404
416
@@ -409,6 +421,10 @@ def render_function(class_name, func_name, sigs, return_type, non_pointer,
409
421
call_postfix = ''
410
422
if return_type != 'Void' and not constructor :
411
423
call_prefix = 'return '
424
+
425
+ if options .wasm64 and (constructor or return_type in interfaces or return_type == 'String' ):
426
+ call_postfix += ')'
427
+
412
428
if not constructor :
413
429
if return_type in interfaces :
414
430
call_prefix += 'wrapPointer('
@@ -420,17 +436,28 @@ def render_function(class_name, func_name, sigs, return_type, non_pointer,
420
436
call_prefix += '!!('
421
437
call_postfix += ')'
422
438
439
+ if options .wasm64 and (constructor or return_type in interfaces or return_type == 'String' ):
440
+ call_prefix += 'Number('
441
+
442
+
423
443
args = [(all_args [i ].identifier .name if isinstance (all_args [i ], WebIDL .IDLArgument ) else ('arg%d' % i )) for i in range (max_args )]
424
444
if not constructor and not is_static :
425
445
body = ' var self = this.ptr;\n '
426
- pre_arg = ['self' ]
446
+ if options .wasm64 :
447
+ pre_arg = ['BigInt(self)' ]
448
+ else :
449
+ pre_arg = ['self' ]
427
450
else :
428
451
body = ''
429
452
pre_arg = []
430
453
431
454
if any (arg .type .isString () or arg .type .isArray () for arg in all_args ):
432
455
body += ' ensureCache.prepare();\n '
433
456
457
+ def is_ptr_arg (i ):
458
+ t = all_args [i ].type
459
+ return (t .isArray () or t .isAny () or t .isString () or t .isObject () or t .isInterface ())
460
+
434
461
for i , (js_arg , arg ) in enumerate (zip (args , all_args )):
435
462
if i >= min_args :
436
463
optional = True
@@ -494,9 +521,11 @@ def render_function(class_name, func_name, sigs, return_type, non_pointer,
494
521
495
522
if do_default :
496
523
if not (arg .type .isArray () and not array_attribute ):
497
- body += " if ({0 } && typeof {0 } === 'object') {0 } = {0 }.ptr;\n " . format ( js_arg )
524
+ body += f " if ({ js_arg } && typeof { js_arg } === 'object') { js_arg } = { js_arg } .ptr;\n "
498
525
if arg .type .isString ():
499
526
body += " else {0} = ensureString({0});\n " .format (js_arg )
527
+ if options .wasm64 and is_ptr_arg (i ):
528
+ body += f' if ({ args [i ]} === null) { args [i ]} = 0;\n '
500
529
else :
501
530
# an array can be received here
502
531
arg_type = arg .type .name
@@ -511,18 +540,45 @@ def render_function(class_name, func_name, sigs, return_type, non_pointer,
511
540
elif arg_type == 'Double' :
512
541
body += " if (typeof {0} == 'object') {{ {0} = ensureFloat64({0}); }}\n " .format (js_arg )
513
542
543
+ call_args = pre_arg
544
+
545
+ for i , arg in enumerate (args ):
546
+ if options .wasm64 and is_ptr_arg (i ):
547
+ arg = f'BigInt({ arg } )'
548
+ call_args .append (arg )
549
+
514
550
c_names = {}
551
+
552
+ def make_call_args (i ):
553
+ if pre_arg :
554
+ i += 1
555
+ return ', ' .join (call_args [:i ])
556
+
515
557
for i in range (min_args , max_args ):
516
- c_names [i ] = 'emscripten_bind_%s_%d' % (bindings_name , i )
517
- 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' )
518
- c_names [max_args ] = 'emscripten_bind_%s_%d' % (bindings_name , max_args )
519
- body += ' %s%s(%s)%s;\n ' % (call_prefix , '_' + c_names [max_args ], ', ' .join (pre_arg + args ), call_postfix )
558
+ c_names [i ] = f'emscripten_bind_{ bindings_name } _{ i } '
559
+ if 'return ' in call_prefix :
560
+ after_call = ''
561
+ else :
562
+ after_call = '; ' + cache + 'return'
563
+ args_for_call = make_call_args (i )
564
+ body += ' if (%s === undefined) { %s_%s(%s)%s%s }\n ' % (args [i ], call_prefix , c_names [i ],
565
+ args_for_call ,
566
+ call_postfix , after_call )
567
+ dbg (call_prefix )
568
+ c_names [max_args ] = f'emscripten_bind_{ bindings_name } _{ max_args } '
569
+ args_for_call = make_call_args (len (args ))
570
+ body += ' %s_%s(%s)%s;\n ' % (call_prefix , c_names [max_args ], args_for_call , call_postfix )
520
571
if cache :
521
- body += ' ' + cache + '\n '
572
+ body += f' { cache } \n '
573
+
574
+ if constructor :
575
+ declare_name = ' ' + func_name
576
+ else :
577
+ declare_name = ''
522
578
mid_js .append (r'''function%s(%s) {
523
579
%s
524
580
};
525
- ''' % (( ' ' + func_name ) if constructor else '' , ', ' .join (args ), body [:- 1 ]))
581
+ ''' % (declare_name , ', ' .join (args ), body [:- 1 ]))
526
582
527
583
# C
528
584
@@ -532,7 +588,8 @@ def render_function(class_name, func_name, sigs, return_type, non_pointer,
532
588
continue
533
589
sig = list (map (full_typename , raw ))
534
590
if array_attribute :
535
- sig = [x .replace ('[]' , '' ) for x in sig ] # for arrays, ignore that this is an array - our get/set methods operate on the elements
591
+ # for arrays, ignore that this is an array - our get/set methods operate on the elements
592
+ sig = [x .replace ('[]' , '' ) for x in sig ]
536
593
537
594
c_arg_types = list (map (type_to_c , sig ))
538
595
c_class_name = type_to_c (class_name , non_pointing = True )
@@ -726,9 +783,9 @@ def add_bounds_check_impl():
726
783
attr = m .identifier .name
727
784
728
785
if m .type .isArray ():
729
- get_sigs = {1 : [Dummy ({ ' type' : WebIDL .BuiltinTypes [WebIDL .IDLBuiltinType .Types .long ]} )]}
730
- set_sigs = {2 : [Dummy ({ ' type' : WebIDL .BuiltinTypes [WebIDL .IDLBuiltinType .Types .long ]} ),
731
- Dummy ({ ' type' : m .type } )]}
786
+ get_sigs = {1 : [Dummy (type = WebIDL .BuiltinTypes [WebIDL .IDLBuiltinType .Types .long ])]}
787
+ set_sigs = {2 : [Dummy (type = WebIDL .BuiltinTypes [WebIDL .IDLBuiltinType .Types .long ]),
788
+ Dummy (type = m .type . inner )]}
732
789
get_call_content = take_addr_if_nonpointer (m ) + 'self->' + attr + '[arg0]'
733
790
set_call_content = 'self->' + attr + '[arg0] = ' + deref_if_nonpointer (m ) + 'arg1'
734
791
if m .getExtendedAttribute ('BoundsChecked' ):
@@ -740,7 +797,7 @@ def add_bounds_check_impl():
740
797
set_call_content = "(%s, %s)" % (bounds_check , set_call_content )
741
798
else :
742
799
get_sigs = {0 : []}
743
- set_sigs = {1 : [Dummy ({ ' type' : m .type } )]}
800
+ set_sigs = {1 : [Dummy (type = m .type )]}
744
801
get_call_content = take_addr_if_nonpointer (m ) + 'self->' + attr
745
802
set_call_content = 'self->' + attr + ' = ' + deref_if_nonpointer (m ) + 'arg0'
746
803
0 commit comments