Skip to content

Commit ea1249c

Browse files
committed
lib: implement interface converter in webidl
1 parent 53ede87 commit ea1249c

File tree

2 files changed

+52
-1
lines changed

2 files changed

+52
-1
lines changed

lib/internal/webidl.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const {
1212
NumberMAX_SAFE_INTEGER,
1313
NumberMIN_SAFE_INTEGER,
1414
ObjectAssign,
15+
ObjectPrototypeIsPrototypeOf,
1516
SafeSet,
1617
String,
1718
SymbolIterator,
@@ -20,6 +21,7 @@ const {
2021

2122
const {
2223
codes: {
24+
ERR_INVALID_ARG_TYPE,
2325
ERR_INVALID_ARG_VALUE,
2426
},
2527
} = require('internal/errors');
@@ -275,20 +277,34 @@ function createSequenceConverter(converter) {
275277
const val = converter(res.value, {
276278
__proto__: null,
277279
...opts,
278-
context: `${opts.context}, index ${array.length}`,
280+
context: `${opts.context}[${array.length}]`,
279281
});
280282
ArrayPrototypePush(array, val);
281283
};
282284
return array;
283285
};
284286
}
285287

288+
// https://webidl.spec.whatwg.org/#js-interface
289+
function createInterfaceConverter(name, prototype) {
290+
return (V, opts = kEmptyObject) => {
291+
// 1. If V implements I, then return the IDL interface type value that
292+
// represents a reference to that platform object.
293+
if (ObjectPrototypeIsPrototypeOf(prototype, V)) return V;
294+
// 2. Throw a TypeError.
295+
throw new ERR_INVALID_ARG_TYPE(
296+
typeof opts.context === 'string' ? opts.context : 'value', name, V,
297+
);
298+
};
299+
}
300+
286301

287302
module.exports = {
288303
type,
289304
converters,
290305
convertToInt,
291306
createEnumConverter,
307+
createInterfaceConverter,
292308
createSequenceConverter,
293309
evenRound,
294310
makeException,

test/parallel/test-internal-webidl.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Flags: --expose-internals
2+
'use strict';
3+
4+
require('../common');
5+
const { describe, it } = require('node:test');
6+
const assert = require('node:assert');
7+
const { createInterfaceConverter } = require('internal/webidl');
8+
9+
describe('internal/webidl', () => {
10+
class Test { t() {} }
11+
class SubTest extends Test {}
12+
const testConverter = createInterfaceConverter('Test', Test.prototype);
13+
14+
it('converts objects that implement the required interface', () => {
15+
const subTest = new SubTest();
16+
const test = new Test();
17+
assert.strictEqual(subTest, testConverter(subTest));
18+
assert.strictEqual(test, testConverter(test));
19+
});
20+
21+
it('throws TypeError when converting objects that do not implement the required interface', () => {
22+
const expectedError = { code: 'ERR_INVALID_ARG_TYPE' };
23+
[
24+
{ t: () => {} },
25+
null,
26+
undefined,
27+
{},
28+
[],
29+
1,
30+
'123',
31+
].forEach((c) => {
32+
assert.throws(() => { testConverter(c); }, expectedError);
33+
});
34+
});
35+
});

0 commit comments

Comments
 (0)