@@ -123,6 +123,28 @@ var fround =
123
123
} ) ( ) ;
124
124
//@ }
125
125
126
+ /// IdlHarnessError ///
127
+ // Entry point
128
+ self . IdlHarnessError = function ( message )
129
+ //@{
130
+ {
131
+ /**
132
+ * Message to be printed as the error's toString invocation.
133
+ */
134
+ this . message = message ;
135
+ } ;
136
+
137
+ IdlHarnessError . prototype = Object . create ( Error . prototype ) ;
138
+
139
+ //@ }
140
+ IdlHarnessError . prototype . toString = function ( )
141
+ //@{
142
+ {
143
+ return this . message ;
144
+ } ;
145
+
146
+ //@ }
147
+
126
148
/// IdlArray ///
127
149
// Entry point
128
150
self . IdlArray = function ( )
@@ -217,7 +239,7 @@ IdlArray.prototype.internal_add_idls = function(parsed_idls, options)
217
239
218
240
if ( options && options . only && options . except )
219
241
{
220
- throw "The only and except options can't be used together."
242
+ throw new IdlHarnessError ( "The only and except options can't be used together." ) ;
221
243
}
222
244
223
245
function should_skip ( name )
@@ -235,7 +257,7 @@ IdlArray.prototype.internal_add_idls = function(parsed_idls, options)
235
257
236
258
parsed_idls . forEach ( function ( parsed_idl )
237
259
{
238
- if ( parsed_idl . type == "interface" && parsed_idl . partial )
260
+ if ( parsed_idl . partial && [ "interface" , "dictionary" ] . includes ( parsed_idl . type ) )
239
261
{
240
262
if ( should_skip ( parsed_idl . name ) )
241
263
{
@@ -280,7 +302,7 @@ IdlArray.prototype.internal_add_idls = function(parsed_idls, options)
280
302
}
281
303
if ( parsed_idl . name in this . members )
282
304
{
283
- throw "Duplicate identifier " + parsed_idl . name ;
305
+ throw new IdlHarnessError ( "Duplicate identifier " + parsed_idl . name ) ;
284
306
}
285
307
switch ( parsed_idl . type )
286
308
{
@@ -374,7 +396,7 @@ IdlArray.prototype.recursively_get_implements = function(interface_name)
374
396
ret = ret . concat ( this . recursively_get_implements ( ret [ i ] ) ) ;
375
397
if ( ret . indexOf ( ret [ i ] ) != ret . lastIndexOf ( ret [ i ] ) )
376
398
{
377
- throw "Circular implements statements involving " + ret [ i ] ;
399
+ throw new IdlHarnessError ( "Circular implements statements involving " + ret [ i ] ) ;
378
400
}
379
401
}
380
402
return ret ;
@@ -404,7 +426,7 @@ IdlArray.prototype.recursively_get_includes = function(interface_name)
404
426
ret = ret . concat ( this . recursively_get_includes ( ret [ i ] ) ) ;
405
427
if ( ret . indexOf ( ret [ i ] ) != ret . lastIndexOf ( ret [ i ] ) )
406
428
{
407
- throw "Circular includes statements involving " + ret [ i ] ;
429
+ throw new IdlHarnessError ( "Circular includes statements involving " + ret [ i ] ) ;
408
430
}
409
431
}
410
432
return ret ;
@@ -532,8 +554,9 @@ IdlArray.prototype.is_json_type = function(type)
532
554
533
555
function exposure_set ( object , default_set ) {
534
556
var exposed = object . extAttrs . filter ( function ( a ) { return a . name == "Exposed" } ) ;
535
- if ( exposed . length > 1 || exposed . length < 0 ) {
536
- throw "Unexpected Exposed extended attributes on " + memberName + ": " + exposed ;
557
+ if ( exposed . length > 1 ) {
558
+ throw new IdlHarnessError (
559
+ `Multiple 'Exposed' extended attributes on ${ object . name } ` ) ;
537
560
}
538
561
539
562
if ( exposed . length === 0 ) {
@@ -567,7 +590,34 @@ function exposed_in(globals) {
567
590
return globals . indexOf ( "Worker" ) >= 0 ||
568
591
globals . indexOf ( "ServiceWorker" ) >= 0 ;
569
592
}
570
- throw "Unexpected global object" ;
593
+ throw new IdlHarnessError ( "Unexpected global object" ) ;
594
+ }
595
+
596
+ //@ }
597
+ /**
598
+ * Asserts that the given error message is thrown for the given function.
599
+ * @param {string|IdlHarnessError } error Expected Error message.
600
+ * @param {Function } idlArrayFunc Function operating on an IdlArray that should throw.
601
+ */
602
+ IdlArray . prototype . assert_throws = function ( error , idlArrayFunc )
603
+ //@{
604
+ {
605
+ try {
606
+ idlArrayFunc . call ( this , this ) ;
607
+ } catch ( e ) {
608
+ if ( e instanceof AssertionError ) {
609
+ throw e ;
610
+ }
611
+ // Assertions for behaviour of the idlharness.js engine.
612
+ if ( error instanceof IdlHarnessError ) {
613
+ error = error . message ;
614
+ }
615
+ if ( e . message !== error ) {
616
+ throw new IdlHarnessError ( `${ idlArrayFunc } threw "${ e } ", not the expected IdlHarnessError "${ error } "` ) ;
617
+ }
618
+ return ;
619
+ }
620
+ throw new IdlHarnessError ( `${ idlArrayFunc } did not throw the expected IdlHarnessError` ) ;
571
621
}
572
622
573
623
//@ }
@@ -581,9 +631,10 @@ IdlArray.prototype.test = function()
581
631
this . partials . forEach ( function ( parsed_idl )
582
632
{
583
633
if ( ! ( parsed_idl . name in this . members )
584
- || ! ( this . members [ parsed_idl . name ] instanceof IdlInterface ) )
634
+ || ! ( this . members [ parsed_idl . name ] instanceof IdlInterface
635
+ || this . members [ parsed_idl . name ] instanceof IdlDictionary ) )
585
636
{
586
- throw " Partial interface " + parsed_idl . name + " with no original interface" ;
637
+ throw new IdlHarnessError ( ` Partial ${ parsed_idl . type } ${ parsed_idl . name } with no original ${ parsed_idl . type } ` ) ;
587
638
}
588
639
if ( parsed_idl . extAttrs )
589
640
{
@@ -633,6 +684,21 @@ IdlArray.prototype.test = function()
633
684
}
634
685
this [ "includes" ] = { } ;
635
686
687
+ // Assert B defined for A : B
688
+ for ( var member of Object . values ( this . members ) . filter ( m => m . base ) ) {
689
+ const lhs = member . name ;
690
+ const rhs = member . base ;
691
+ if ( ! ( rhs in this . members ) ) throw new IdlHarnessError ( `${ lhs } inherits ${ rhs } , but ${ rhs } is undefined.` ) ;
692
+ const lhs_is_interface = this . members [ lhs ] instanceof IdlInterface ;
693
+ const rhs_is_interface = this . members [ rhs ] instanceof IdlInterface ;
694
+ if ( rhs_is_interface != lhs_is_interface ) {
695
+ if ( ! lhs_is_interface ) throw new IdlHarnessError ( `${ lhs } inherits ${ rhs } , but ${ lhs } is not an interface.` ) ;
696
+ if ( ! rhs_is_interface ) throw new IdlHarnessError ( `${ lhs } inherits ${ rhs } , but ${ rhs } is not an interface.` ) ;
697
+ }
698
+ // Check for circular dependencies.
699
+ member . get_inheritance_stack ( ) ;
700
+ }
701
+
636
702
Object . getOwnPropertyNames ( this . members ) . forEach ( function ( memberName ) {
637
703
var member = this . members [ memberName ] ;
638
704
if ( ! ( member instanceof IdlInterface ) ) {
@@ -848,7 +914,7 @@ IdlArray.prototype.assert_type_is = function(value, type)
848
914
849
915
if ( ! ( type in this . members ) )
850
916
{
851
- throw "Unrecognized type " + type ;
917
+ throw new IdlHarnessError ( "Unrecognized type " + type ) ;
852
918
}
853
919
854
920
if ( this . members [ type ] instanceof IdlInterface )
@@ -876,7 +942,7 @@ IdlArray.prototype.assert_type_is = function(value, type)
876
942
}
877
943
else
878
944
{
879
- throw "Type " + type + " isn't an interface or dictionary" ;
945
+ throw new IdlHarnessError ( "Type " + type + " isn't an interface or dictionary" ) ;
880
946
}
881
947
} ;
882
948
//@ }
@@ -1061,6 +1127,10 @@ IdlInterface.prototype.get_inheritance_stack = function() {
1061
1127
var base = this . array . members [ idl_interface . base ] ;
1062
1128
if ( ! base ) {
1063
1129
throw new Error ( idl_interface . type + " " + idl_interface . base + " not found (inherited by " + idl_interface . name + ")" ) ;
1130
+ } else if ( stack . indexOf ( base ) > - 1 ) {
1131
+ stack . push ( base ) ;
1132
+ let dep_chain = stack . map ( i => i . name ) . join ( ',' ) ;
1133
+ throw new IdlHarnessError ( `${ this . name } has a circular dependency: ${ dep_chain } ` ) ;
1064
1134
}
1065
1135
idl_interface = base ;
1066
1136
stack . push ( idl_interface ) ;
@@ -1345,13 +1415,13 @@ IdlInterface.prototype.test_self = function()
1345
1415
{
1346
1416
var aliasAttrs = this . extAttrs . filter ( function ( o ) { return o . name === "LegacyWindowAlias" ; } ) ;
1347
1417
if ( aliasAttrs . length > 1 ) {
1348
- throw "Invalid IDL: multiple LegacyWindowAlias extended attributes on " + this . name ;
1418
+ throw new IdlHarnessError ( "Invalid IDL: multiple LegacyWindowAlias extended attributes on " + this . name ) ;
1349
1419
}
1350
1420
if ( this . is_callback ( ) ) {
1351
- throw "Invalid IDL: LegacyWindowAlias extended attribute on non-interface " + this . name ;
1421
+ throw new IdlHarnessError ( "Invalid IDL: LegacyWindowAlias extended attribute on non-interface " + this . name ) ;
1352
1422
}
1353
1423
if ( this . exposureSet . indexOf ( "Window" ) === - 1 ) {
1354
- throw "Invalid IDL: LegacyWindowAlias extended attribute on " + this . name + " which is not exposed in Window" ;
1424
+ throw new IdlHarnessError ( "Invalid IDL: LegacyWindowAlias extended attribute on " + this . name + " which is not exposed in Window" ) ;
1355
1425
}
1356
1426
// TODO: when testing of [NoInterfaceObject] interfaces is supported,
1357
1427
// check that it's not specified together with LegacyWindowAlias.
@@ -1360,7 +1430,7 @@ IdlInterface.prototype.test_self = function()
1360
1430
1361
1431
var rhs = aliasAttrs [ 0 ] . rhs ;
1362
1432
if ( ! rhs ) {
1363
- throw "Invalid IDL: LegacyWindowAlias extended attribute on " + this . name + " without identifier" ;
1433
+ throw new IdlHarnessError ( "Invalid IDL: LegacyWindowAlias extended attribute on " + this . name + " without identifier" ) ;
1364
1434
}
1365
1435
var aliases ;
1366
1436
if ( rhs . type === "identifier-list" ) {
@@ -1621,7 +1691,6 @@ IdlInterface.prototype.test_self = function()
1621
1691
this . name + '.prototype should not have @@unscopables' ) ;
1622
1692
}
1623
1693
} . bind ( this ) , this . name + ' interface: existence and properties of interface prototype object\'s @@unscopables property' ) ;
1624
-
1625
1694
} ;
1626
1695
1627
1696
//@ }
@@ -1733,7 +1802,7 @@ IdlInterface.prototype.test_member_const = function(member)
1733
1802
//@{
1734
1803
{
1735
1804
if ( ! this . has_constants ( ) ) {
1736
- throw "Internal error: test_member_const called without any constants" ;
1805
+ throw new IdlHarnessError ( "Internal error: test_member_const called without any constants" ) ;
1737
1806
}
1738
1807
1739
1808
test ( function ( )
@@ -2289,7 +2358,7 @@ IdlInterface.prototype.test_object = function(desc)
2289
2358
{
2290
2359
if ( ! ( current_interface . name in this . array . members ) )
2291
2360
{
2292
- throw "Interface " + current_interface . name + " not found (inherited by " + this . name + ")" ;
2361
+ throw new IdlHarnessError ( "Interface " + current_interface . name + " not found (inherited by " + this . name + ")" ) ;
2293
2362
}
2294
2363
if ( current_interface . prevent_multiple_testing && current_interface . already_tested )
2295
2364
{
@@ -2379,6 +2448,7 @@ IdlInterface.prototype.test_interface_of = function(desc, obj, exception, expect
2379
2448
}
2380
2449
if ( ! exposed_in ( exposure_set ( member , this . exposureSet ) ) ) {
2381
2450
test ( function ( ) {
2451
+ assert_equals ( exception , null , "Unexpected exception when evaluating object" ) ;
2382
2452
assert_false ( member . name in obj ) ;
2383
2453
} . bind ( this ) , this . name + " interface: " + desc + ' must not have property "' + member . name + '"' ) ;
2384
2454
continue ;
0 commit comments