@@ -99,6 +99,7 @@ const kResourceInfo = {
9999 'unmap' ,
100100 'usage' ,
101101 ] ,
102+ getters : [ 'label' , 'mapState' , 'size' , 'usage' ] ,
102103 } ,
103104 texture : {
104105 create ( t : GPUTest ) {
@@ -121,6 +122,17 @@ const kResourceInfo = {
121122 'usage' ,
122123 'width' ,
123124 ] ,
125+ getters : [
126+ 'depthOrArrayLayers' ,
127+ 'dimension' ,
128+ 'format' ,
129+ 'height' ,
130+ 'label' ,
131+ 'mipLevelCount' ,
132+ 'sampleCount' ,
133+ 'usage' ,
134+ 'width' ,
135+ ] ,
124136 } ,
125137 querySet : {
126138 create ( t : GPUTest ) {
@@ -130,12 +142,14 @@ const kResourceInfo = {
130142 } ) ;
131143 } ,
132144 requiredKeys : [ 'count' , 'destroy' , 'label' , 'type' ] ,
145+ getters : [ 'count' , 'label' , 'type' ] ,
133146 } ,
134147 adapter : {
135148 create ( t : GPUTest ) {
136149 return t . adapter ;
137150 } ,
138151 requiredKeys : [ 'features' , 'info' , 'limits' , 'requestDevice' ] ,
152+ getters : [ 'features' , 'info' , 'limits' ] ,
139153 } ,
140154 device : {
141155 create ( t : GPUTest ) {
@@ -171,18 +185,21 @@ const kResourceInfo = {
171185 'queue' ,
172186 'removeEventListener' ,
173187 ] ,
188+ getters : [ 'adapterInfo' , 'features' , 'label' , 'limits' , 'lost' , 'onuncapturederror' , 'queue' ] ,
174189 } ,
175190 'adapter.limits' : {
176191 create ( t : GPUTest ) {
177192 return t . adapter . limits ;
178193 } ,
179194 requiredKeys : kSpecifiedLimits ,
195+ getters : kSpecifiedLimits ,
180196 } ,
181197 'device.limits' : {
182198 create ( t : GPUTest ) {
183199 return t . device . limits ;
184200 } ,
185201 requiredKeys : kSpecifiedLimits ,
202+ getters : kSpecifiedLimits ,
186203 } ,
187204} as const ;
188205const kResources = keysOf ( kResourceInfo ) ;
@@ -231,7 +248,7 @@ g.test('obj,Object_keys')
231248 . fn ( t => {
232249 const { type } = t . params ;
233250 const obj = createResource ( t , type ) ;
234- t . expect ( objectEquals ( [ ...Object . keys ( obj ) ] , [ ] ) , `Object.keys( [...${ type } ] === []` ) ;
251+ t . expect ( objectEquals ( [ ...Object . keys ( obj ) ] , [ ] ) , `[...Object.keys( ${ type } ) ] === []` ) ;
235252 } ) ;
236253
237254g . test ( 'obj,spread' )
@@ -338,3 +355,110 @@ g.test('limits')
338355 ) ;
339356 }
340357 } ) ;
358+
359+ g . test ( 'getter_replacement' )
360+ . desc (
361+ `
362+ Test that replacing getters on class prototypes works
363+
364+ This is a common pattern for shims and debugging libraries so make sure this pattern works.
365+ `
366+ )
367+ . params ( u => u . combine ( 'type' , kResources ) )
368+ . fn ( t => {
369+ const { type } = t . params ;
370+ const { getters } = kResourceInfo [ type ] ;
371+
372+ const obj = createResource ( t , type ) ;
373+ for ( const getter of getters ) {
374+ // Check it's not 'ownProperty`
375+ const properties = Object . getOwnPropertyDescriptor ( obj , getter ) ;
376+ t . expect (
377+ properties === undefined ,
378+ `Object.getOwnPropertyDescriptor(instance of ${ type } , '${ getter } ') === undefined`
379+ ) ;
380+
381+ // Check it's actually a getter that returns a non-function value.
382+ const origValue = ( obj as unknown as Record < string , ( ) => unknown > ) [ getter ] ;
383+ t . expect ( typeof origValue !== 'function' , `instance of ${ type } .${ getter } !== 'function'` ) ;
384+
385+ // check replacing the getter on constructor works.
386+ const ctorPrototype = obj . constructor . prototype ;
387+ const origProperties = Object . getOwnPropertyDescriptor ( ctorPrototype , getter ) ;
388+ t . expect (
389+ ! ! origProperties ,
390+ `Object.getOwnPropertyDescriptor(${ type } , '${ getter } ') !== undefined`
391+ ) ;
392+ try {
393+ Object . defineProperty ( ctorPrototype , getter , {
394+ get ( ) {
395+ return 'testGetterValue' ;
396+ } ,
397+ } ) ;
398+ const value = ( obj as unknown as Record < string , string > ) [ getter ] ;
399+ t . expect (
400+ value === 'testGetterValue' ,
401+ `replacing getter: '${ getter } ' on ${ type } returns test value`
402+ ) ;
403+ } finally {
404+ Object . defineProperty ( ctorPrototype , getter , origProperties ! ) ;
405+ }
406+
407+ // Check it turns the same value after restoring as before restoring.
408+ const afterValue = ( obj as unknown as Record < string , ( ) => unknown > ) [ getter ] ;
409+ t . expect (
410+ afterValue === origValue ,
411+ `able to restore getter for instance of ${ type } .${ getter } `
412+ ) ;
413+ }
414+ } ) ;
415+
416+ g . test ( 'method_replacement' )
417+ . desc (
418+ `
419+ Test that replacing methods on class prototypes works
420+
421+ This is a common pattern for shims and debugging libraries so make sure this pattern works.
422+ `
423+ )
424+ . params ( u => u . combine ( 'type' , kResources ) )
425+ . fn ( t => {
426+ const { type } = t . params ;
427+ const { requiredKeys, getters } = kResourceInfo [ type ] ;
428+ const gettersSet = new Set < string > ( getters ) ;
429+ const methods = requiredKeys . filter ( k => ! gettersSet . has ( k ) ) ;
430+
431+ const obj = createResource ( t , type ) ;
432+ for ( const method of methods ) {
433+ const ctorPrototype = obj . constructor . prototype ;
434+ const origFunc = ctorPrototype [ method ] ;
435+
436+ t . expect ( typeof origFunc === 'function' , `${ type } .prototype.${ method } is a function` ) ;
437+
438+ // Check the function the prototype and the one on the object are the same
439+ t . expect (
440+ ( obj as unknown as Record < string , unknown > ) [ method ] === origFunc ,
441+ `instance of ${ type } .${ method } === ${ type } .prototype.${ method } `
442+ ) ;
443+
444+ // Check replacing the method on constructor works.
445+ try {
446+ ( ctorPrototype as unknown as Record < string , unknown > ) [ method ] = function ( ) {
447+ return 'testMethodValue' ;
448+ } ;
449+ const value = ( obj as unknown as Record < string , ( ) => string > ) [ method ] ( ) ;
450+ t . expect (
451+ value === 'testMethodValue' ,
452+ `replacing method: '${ method } ' on ${ type } returns test value`
453+ ) ;
454+ } finally {
455+ ( ctorPrototype as unknown as Record < string , unknown > ) [ method ] = origFunc ;
456+ }
457+
458+ // Check the function the prototype and the one on the object are the same after restoring.
459+ t . expect (
460+ ( obj as unknown as Record < string , unknown > ) [ method ] === origFunc ,
461+ `instance of ${ type } .${ method } === ${ type } .prototype.${ method } `
462+ ) ;
463+ }
464+ } ) ;
0 commit comments