88https://emscripten.org/docs/porting/connecting_cpp_and_javascript/WebIDL-Binder.html
99"""
1010
11+ import argparse
1112import os
1213import sys
1314from typing import List
@@ -55,8 +56,15 @@ def getExtendedAttribute(self, _name):
5556 return None
5657
5758
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
6068cpp_output = output_base + '.cpp'
6169js_output = output_base + '.js'
6270
@@ -89,7 +97,7 @@ def getExtendedAttribute(self, _name):
8997#include <emscripten.h>
9098#include <stdlib.h>
9199
92- EM_JS_DEPS(webidl_binder, "$intArrayFromString,$UTF8ToString");
100+ EM_JS_DEPS(webidl_binder, "$intArrayFromString,$UTF8ToString,$alignMemory ");
93101''' ]
94102
95103mid_c = ['''
@@ -214,7 +222,7 @@ def build_constructor(name):
214222 assert(ensureCache.buffer);
215223 var bytes = view.BYTES_PER_ELEMENT;
216224 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
218226 var ret;
219227 if (ensureCache.pos + len >= ensureCache.size) {
220228 // we failed to allocate in the buffer, ensureCache time around :(
@@ -230,13 +238,7 @@ def build_constructor(name):
230238 return ret;
231239 },
232240 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;
240242 for (var i = 0; i < array.length; i++) {
241243 view[offset + i] = array[i];
242244 }
@@ -415,6 +417,11 @@ def render_function(class_name, func_name, sigs, return_type, non_pointer,
415417 call_postfix = ''
416418 if return_type != 'Void' and not constructor :
417419 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+
418425 if not constructor :
419426 if return_type in interfaces :
420427 call_prefix += 'wrapPointer('
@@ -426,17 +433,27 @@ def render_function(class_name, func_name, sigs, return_type, non_pointer,
426433 call_prefix += '!!('
427434 call_postfix += ')'
428435
436+ if options .wasm64 and ptr_rtn :
437+ call_prefix += 'Number('
438+
429439 args = [(all_args [i ].identifier .name if isinstance (all_args [i ], WebIDL .IDLArgument ) else ('arg%d' % i )) for i in range (max_args )]
430440 if not constructor and not is_static :
431441 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' ]
433446 else :
434447 body = ''
435448 pre_arg = []
436449
437450 if any (arg .type .isString () or arg .type .isArray () for arg in all_args ):
438451 body += ' ensureCache.prepare();\n '
439452
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+
440457 for i , (js_arg , arg ) in enumerate (zip (args , all_args )):
441458 if i >= min_args :
442459 optional = True
@@ -500,9 +517,11 @@ def render_function(class_name, func_name, sigs, return_type, non_pointer,
500517
501518 if do_default :
502519 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 "
504521 if arg .type .isString ():
505522 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 '
506525 else :
507526 # an array can be received here
508527 arg_type = arg .type .name
@@ -517,18 +536,45 @@ def render_function(class_name, func_name, sigs, return_type, non_pointer,
517536 elif arg_type == 'Double' :
518537 body += " if (typeof {0} == 'object') {{ {0} = ensureFloat64({0}); }}\n " .format (js_arg )
519538
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+
520546 c_names = {}
547+
548+ def make_call_args (i ):
549+ if pre_arg :
550+ i += 1
551+ return ', ' .join (call_args [:i ])
552+
521553 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 )
526567 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 = ''
528574 mid_js .append (r'''function%s(%s) {
529575%s
530576};
531- ''' % (( ' ' + func_name ) if constructor else '' , ', ' .join (args ), body [:- 1 ]))
577+ ''' % (declare_name , ', ' .join (args ), body [:- 1 ]))
532578
533579 # C
534580
@@ -538,7 +584,8 @@ def render_function(class_name, func_name, sigs, return_type, non_pointer,
538584 continue
539585 sig = list (map (full_typename , raw ))
540586 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 ]
542589
543590 c_arg_types = list (map (type_to_c , sig ))
544591 c_class_name = type_to_c (class_name , non_pointing = True )
0 commit comments