@@ -27,7 +27,7 @@ use crate::decode;
27
27
use crate :: descriptor:: { Descriptor , Function } ;
28
28
use crate :: descriptors:: WasmBindgenDescriptorsSection ;
29
29
use crate :: intrinsic:: Intrinsic ;
30
- use failure:: { bail, Error } ;
30
+ use failure:: { bail, format_err , Error } ;
31
31
use std:: borrow:: Cow ;
32
32
use std:: collections:: { HashMap , HashSet } ;
33
33
use std:: path:: PathBuf ;
@@ -504,6 +504,10 @@ pub fn process(
504
504
cx. program ( program) ?;
505
505
}
506
506
507
+ if let Some ( standard) = cx. module . customs . delete_typed :: < ast:: WebidlBindings > ( ) {
508
+ cx. standard ( & standard) ?;
509
+ }
510
+
507
511
cx. verify ( ) ?;
508
512
509
513
let bindings = cx. module . customs . add ( cx. bindings ) ;
@@ -1287,6 +1291,171 @@ impl<'a> Context<'a> {
1287
1291
Ok ( JsImport { name, fields } )
1288
1292
}
1289
1293
1294
+ /// Processes bindings from a standard WebIDL bindings custom section.
1295
+ ///
1296
+ /// No module coming out of the Rust compiler will have one of these, but
1297
+ /// eventually there's going to be other producers of the WebIDL bindings
1298
+ /// custom section as well. This functionality is intended to allow
1299
+ /// `wasm-bindgen`-the-CLI-tool to act as a polyfill for those modules as
1300
+ /// well as Rust modules.
1301
+ ///
1302
+ /// Here a standard `WebidlBindings` custom section is taken and we process
1303
+ /// that into our own internal data structures to ensure that we have a
1304
+ /// binding listed for all the described bindings.
1305
+ ///
1306
+ /// In other words, this is a glorified conversion from the "official"
1307
+ /// WebIDL bindings custom section into the wasm-bindgen internal
1308
+ /// representation.
1309
+ fn standard ( & mut self , std : & ast:: WebidlBindings ) -> Result < ( ) , Error > {
1310
+ for ( _id, bind) in std. binds . iter ( ) {
1311
+ let binding = self . standard_binding ( std, bind) ?;
1312
+ let func = self . module . funcs . get ( bind. func ) ;
1313
+ match & func. kind {
1314
+ walrus:: FunctionKind :: Import ( i) => {
1315
+ let id = i. import ;
1316
+ self . standard_import ( binding, id) ?;
1317
+ }
1318
+ walrus:: FunctionKind :: Local ( _) => {
1319
+ let export = self
1320
+ . module
1321
+ . exports
1322
+ . iter ( )
1323
+ . find ( |e| match e. item {
1324
+ walrus:: ExportItem :: Function ( f) => f == bind. func ,
1325
+ _ => false ,
1326
+ } )
1327
+ . ok_or_else ( || format_err ! ( "missing export function for webidl binding" ) ) ?;
1328
+ let id = export. id ( ) ;
1329
+ self . standard_export ( binding, id) ?;
1330
+ }
1331
+ walrus:: FunctionKind :: Uninitialized ( _) => unreachable ! ( ) ,
1332
+ }
1333
+ }
1334
+ Ok ( ( ) )
1335
+ }
1336
+
1337
+ /// Creates a wasm-bindgen-internal `Binding` from an official `Bind`
1338
+ /// structure specified in the upstream binary format.
1339
+ ///
1340
+ /// This will largely just copy some things into our own arenas but also
1341
+ /// processes the list of binding expressions into our own representations.
1342
+ fn standard_binding (
1343
+ & mut self ,
1344
+ std : & ast:: WebidlBindings ,
1345
+ bind : & ast:: Bind ,
1346
+ ) -> Result < Binding , Error > {
1347
+ let binding: & ast:: FunctionBinding = std
1348
+ . bindings
1349
+ . get ( bind. binding )
1350
+ . ok_or_else ( || format_err ! ( "bad binding id" ) ) ?;
1351
+ let ( wasm_ty, webidl_ty, incoming, outgoing) = match binding {
1352
+ ast:: FunctionBinding :: Export ( e) => (
1353
+ e. wasm_ty ,
1354
+ e. webidl_ty ,
1355
+ e. params . bindings . as_slice ( ) ,
1356
+ e. result . bindings . as_slice ( ) ,
1357
+ ) ,
1358
+ ast:: FunctionBinding :: Import ( e) => (
1359
+ e. wasm_ty ,
1360
+ e. webidl_ty ,
1361
+ e. result . bindings . as_slice ( ) ,
1362
+ e. params . bindings . as_slice ( ) ,
1363
+ ) ,
1364
+ } ;
1365
+ let webidl_ty = copy_ty ( & mut self . bindings . types , webidl_ty, & std. types ) ;
1366
+ let webidl_ty = match webidl_ty {
1367
+ ast:: WebidlTypeRef :: Id ( id) => <ast:: WebidlFunction as ast:: WebidlTypeId >:: wrap ( id) ,
1368
+ _ => bail ! ( "invalid webidl type listed" ) ,
1369
+ } ;
1370
+ return Ok ( Binding {
1371
+ wasm_ty,
1372
+ webidl_ty,
1373
+ incoming : incoming
1374
+ . iter ( )
1375
+ . cloned ( )
1376
+ . map ( NonstandardIncoming :: Standard )
1377
+ . collect ( ) ,
1378
+ outgoing : outgoing
1379
+ . iter ( )
1380
+ . cloned ( )
1381
+ . map ( NonstandardOutgoing :: Standard )
1382
+ . collect ( ) ,
1383
+ return_via_outptr : None ,
1384
+ } ) ;
1385
+
1386
+ /// Recursively clones `ty` into` dst` where it originally indexes
1387
+ /// values in `src`, returning a new type ref which indexes inside of
1388
+ /// `dst`.
1389
+ fn copy_ty (
1390
+ dst : & mut ast:: WebidlTypes ,
1391
+ ty : ast:: WebidlTypeRef ,
1392
+ src : & ast:: WebidlTypes ,
1393
+ ) -> ast:: WebidlTypeRef {
1394
+ let id = match ty {
1395
+ ast:: WebidlTypeRef :: Id ( id) => id,
1396
+ ast:: WebidlTypeRef :: Scalar ( _) => return ty,
1397
+ } ;
1398
+ let ty: & ast:: WebidlCompoundType = src. get ( id) . unwrap ( ) ;
1399
+ match ty {
1400
+ ast:: WebidlCompoundType :: Function ( f) => {
1401
+ let params = f
1402
+ . params
1403
+ . iter ( )
1404
+ . map ( |param| copy_ty ( dst, * param, src) )
1405
+ . collect ( ) ;
1406
+ let result = f. result . map ( |ty| copy_ty ( dst, ty, src) ) ;
1407
+ dst. insert ( ast:: WebidlFunction {
1408
+ kind : f. kind . clone ( ) ,
1409
+ params,
1410
+ result,
1411
+ } )
1412
+ . into ( )
1413
+ }
1414
+ _ => unimplemented ! ( ) ,
1415
+ }
1416
+ }
1417
+ }
1418
+
1419
+ /// Registers that `id` has a `binding` which was read from a standard
1420
+ /// webidl bindings section, so the source of `id` is its actual module/name
1421
+ /// listed in the wasm module.
1422
+ fn standard_import ( & mut self , binding : Binding , id : walrus:: ImportId ) -> Result < ( ) , Error > {
1423
+ let import = self . module . imports . get ( id) ;
1424
+ let js = JsImport {
1425
+ name : JsImportName :: Module {
1426
+ module : import. module . clone ( ) ,
1427
+ name : import. name . clone ( ) ,
1428
+ } ,
1429
+ fields : Vec :: new ( ) ,
1430
+ } ;
1431
+ let value = AuxValue :: Bare ( js) ;
1432
+ assert ! ( self
1433
+ . aux
1434
+ . import_map
1435
+ . insert( id, AuxImport :: Value ( value) )
1436
+ . is_none( ) ) ;
1437
+ assert ! ( self . bindings. imports. insert( id, binding) . is_none( ) ) ;
1438
+
1439
+ Ok ( ( ) )
1440
+ }
1441
+
1442
+ /// Registers that `id` has a `binding` and comes from a standard webidl
1443
+ /// bindings section so it doesn't have any documentation or debug names we
1444
+ /// can work with.
1445
+ fn standard_export ( & mut self , binding : Binding , id : walrus:: ExportId ) -> Result < ( ) , Error > {
1446
+ let export = self . module . exports . get ( id) ;
1447
+ let kind = AuxExportKind :: Function ( export. name . clone ( ) ) ;
1448
+ let export = AuxExport {
1449
+ debug_name : format ! ( "standard export {:?}" , id) ,
1450
+ comments : String :: new ( ) ,
1451
+ arg_names : None ,
1452
+ kind,
1453
+ } ;
1454
+ assert ! ( self . aux. export_map. insert( id, export) . is_none( ) ) ;
1455
+ assert ! ( self . bindings. exports. insert( id, binding) . is_none( ) ) ;
1456
+ Ok ( ( ) )
1457
+ }
1458
+
1290
1459
/// Perform a small verification pass over the module to perform some
1291
1460
/// internal sanity checks.
1292
1461
fn verify ( & self ) -> Result < ( ) , Error > {
0 commit comments