Skip to content

Commit c1c5e42

Browse files
committed
Check more JavaScript features.
getter_replacement fails on dawn.node. If I understand correctly it's because the getters are placed on the instances, not on the class prototype.
1 parent 5a937b0 commit c1c5e42

File tree

1 file changed

+125
-1
lines changed

1 file changed

+125
-1
lines changed

src/webgpu/idl/javascript.spec.ts

Lines changed: 125 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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;
188205
const 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

237254
g.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

Comments
 (0)