Skip to content

Commit

Permalink
fix: correct types for emscripten JSImplementation method arguments
Browse files Browse the repository at this point in the history
  • Loading branch information
isaac-mason committed Mar 20, 2024
1 parent 798124e commit 7b949de
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 25 deletions.
5 changes: 5 additions & 0 deletions .changeset/serious-foxes-roll.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"webidl-dts-gen": minor
---

fix: correct types for emscripten JSImplementation method arguments
45 changes: 20 additions & 25 deletions packages/webidl-dts-gen/src/convert-idl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,10 +209,9 @@ function isFrozenArrayAttribute(member: webidl2.IDLInterfaceMemberType | webidl2
return member.type === 'attribute' && member.idlType.generic === 'FrozenArray'
}

function convertInterface(
idl: webidl2.InterfaceType | webidl2.DictionaryType | webidl2.InterfaceMixinType | webidl2.NamespaceType,
options: Options,
) {
type InterfaceIDL = webidl2.InterfaceType | webidl2.DictionaryType | webidl2.InterfaceMixinType | webidl2.NamespaceType

function convertInterface(idl: InterfaceIDL, options: Options) {
const members: (ts.TypeElement | ts.ClassElement)[] = []
const inheritance: ts.ExpressionWithTypeArguments[] = []
if ('inheritance' in idl && idl.inheritance) {
Expand Down Expand Up @@ -253,7 +252,7 @@ function convertInterface(
if (member.name === idl.name) {
members.push(convertMemberConstructor(member, options))
} else {
members.push(convertMemberOperation(member, options))
members.push(convertMemberOperation(idl, member, options))
}
break
case 'constructor':
Expand Down Expand Up @@ -346,7 +345,7 @@ function createEmscriptenAttributeGetter(value: webidl2.AttributeMemberType) {
let parameters: ts.ParameterDeclaration[]

if (isFrozenArrayAttribute(value)) {
idlType = (value.idlType.idlType[0] as unknown as webidl2.IDLTypeDescription)
idlType = value.idlType.idlType[0] as unknown as webidl2.IDLTypeDescription
parameters = [
ts.factory.createParameterDeclaration(
[],
Expand Down Expand Up @@ -374,7 +373,7 @@ function createEmscriptenAttributeSetter(value: webidl2.AttributeMemberType) {
let parameters: ts.ParameterDeclaration[]

if (isFrozenArrayAttribute(value)) {
idlType = (value.idlType.idlType[0] as unknown as webidl2.IDLTypeDescription)
idlType = value.idlType.idlType[0] as unknown as webidl2.IDLTypeDescription
parameters = [
ts.factory.createParameterDeclaration(
[],
Expand All @@ -383,25 +382,11 @@ function createEmscriptenAttributeSetter(value: webidl2.AttributeMemberType) {
undefined,
ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword),
),
ts.factory.createParameterDeclaration(
[],
undefined,
value.name,
undefined,
convertType(idlType),
),
ts.factory.createParameterDeclaration([], undefined, value.name, undefined, convertType(idlType)),
]
} else {
idlType = value.idlType
parameters = [
ts.factory.createParameterDeclaration(
[],
undefined,
value.name,
undefined,
convertType(idlType),
),
]
parameters = [ts.factory.createParameterDeclaration([], undefined, value.name, undefined, convertType(idlType))]
}

return createMethod({
Expand All @@ -412,8 +397,10 @@ function createEmscriptenAttributeSetter(value: webidl2.AttributeMemberType) {
})
}

function convertMemberOperation(idl: webidl2.OperationMemberType, { emscripten }: Options) {
const parameters = idl.arguments.map(convertArgument)
function convertMemberOperation(parent: InterfaceIDL, idl: webidl2.OperationMemberType, { emscripten }: Options) {
const emscriptenJSImplementationMethod = emscripten && parent.extAttrs.some((attr) => attr.name === 'JSImplementation')

const parameters = idl.arguments.map(emscriptenJSImplementationMethod ? convertEmscriptenJSImplementationArgument : convertArgument)
const modifiers: ts.Modifier[] = []

// emscripten uses static for binding to c++, but exposes the method on the prototype
Expand Down Expand Up @@ -479,6 +466,14 @@ function convertArgument(idl: webidl2.Argument) {
return ts.factory.createParameterDeclaration([], undefined, idl.name, optional, convertType(idl.idlType))
}

function convertEmscriptenJSImplementationArgument(idl: webidl2.Argument) {
// JSImplementation method arguments are currently only passed as numeric types and pointers
// May need to change this to support DOMString in future: https://github.com/emscripten-core/emscripten/issues/10705
const numberType = makeFinalType(ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword), idl.idlType)

return ts.factory.createParameterDeclaration([], undefined, idl.name, undefined, numberType)
}

function makeFinalType(type: ts.TypeNode, idl: webidl2.IDLTypeDescription): ts.TypeNode {
if (idl.nullable) {
return ts.factory.createUnionTypeNode([type, ts.factory.createLiteralTypeNode(ts.factory.createNull())])
Expand Down
14 changes: 14 additions & 0 deletions packages/webidl-dts-gen/tst/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,20 @@ describe('convert', () => {
expect(ts).toContain('sIdentity(): Quat;')
expect(ts).not.toContain('static sIdentity(): Quat;')
})

it('supports correct types for JSImplementation', async () => {
const idl = multiLine(
'[JSImplementation="ShapeFilter"]', //
'interface ShapeFilterJS {', //
' void ShapeFilterJS();', //
' [Const] boolean ShouldCollide([Const] Shape inShape2, [Const, Ref] SubShapeID inSubShapeIDOfShape2);', //
'};', //
)

const ts = await convert(idl, { emscripten: true })

expect(ts).toContain('ShouldCollide(inShape2: number, inSubShapeIDOfShape2: number): boolean;')
})
})
})

Expand Down

0 comments on commit 7b949de

Please sign in to comment.