Skip to content

Commit fcdaf29

Browse files
committed
refactor(emitter): pass modified type for conversion instead of string replacement
1 parent 760919a commit fcdaf29

File tree

1 file changed

+60
-29
lines changed

1 file changed

+60
-29
lines changed

src/build/emitter.ts

Lines changed: 60 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -371,17 +371,39 @@ export function emitWebIdl(
371371
obj: Browser.Typed,
372372
forReturn: boolean,
373373
): string {
374+
let type: string;
374375
if (obj.overrideType) {
375-
return obj.nullable ? makeNullable(obj.overrideType) : obj.overrideType;
376+
type = obj.overrideType;
377+
} else {
378+
if (!obj.type) {
379+
throw new Error("Missing 'type' field in " + JSON.stringify(obj));
380+
}
381+
type = convertDomTypeToTsTypeWorker(obj, forReturn);
382+
if (type === "Promise<undefined>") {
383+
type = "Promise<void>";
384+
}
376385
}
377-
if (!obj.type) {
378-
throw new Error("Missing 'type' field in " + JSON.stringify(obj));
386+
387+
if (obj.additionalTypes) {
388+
const additional = obj.additionalTypes
389+
.filter((t) => t !== "undefined")
390+
.map((t) => convertDomTypeToTsTypeSimple(t));
391+
if (additional.length > 0) {
392+
type = distinct([type, ...additional]).join(" | ");
393+
}
379394
}
380-
let type = convertDomTypeToTsTypeWorker(obj, forReturn);
381-
if (type === "Promise<undefined>") {
382-
type = "Promise<void>";
395+
396+
if (obj.nullable) {
397+
type = makeNullable(type);
398+
}
399+
400+
if (obj.additionalTypes?.includes("undefined")) {
401+
if (!type.split(" | ").includes("undefined")) {
402+
type += " | undefined";
403+
}
383404
}
384-
return obj.nullable ? makeNullable(type) : type;
405+
406+
return type;
385407
}
386408

387409
function convertDomTypeToTsType(obj: Browser.Typed) {
@@ -408,22 +430,19 @@ export function emitWebIdl(
408430
return "Iterable";
409431
}
410432

411-
if (!obj.additionalTypes && typeof obj.type === "string") {
433+
if (typeof obj.type === "string") {
412434
return convertDomTypeToTsTypeSimple(obj.type);
413435
} else {
414-
const types =
415-
typeof obj.type === "string"
416-
? [{ ...obj, additionalTypes: undefined }]
417-
: obj.type;
418-
types.push(...(obj.additionalTypes ?? []).map((t) => ({ type: t })));
436+
const types = obj.type;
419437

420438
// propagate `any`
421-
const converted = types.map((t) =>
439+
let converted = types.map((t) =>
422440
convertDomTypeToTsTypeWorker(t, forReturn),
423441
);
424442
if (converted.includes("any")) {
425443
return "any";
426444
}
445+
converted = distinct(converted);
427446

428447
// convert `ArrayBuffer | SharedArrayBuffer` into `ArrayBufferLike` to be pre-ES2017 friendly.
429448
const arrayBufferIndex = converted.indexOf("ArrayBuffer");
@@ -900,24 +919,28 @@ export function emitWebIdl(
900919
printer.printLine("/** @deprecated */");
901920
printer.printLine("declare const name: void;");
902921
} else {
903-
let pType: string;
922+
let pForType: Browser.Property = p;
904923
if (!p.overrideType && isEventHandler(p)) {
905924
// Sometimes event handlers with the same name may actually handle different
906925
// events in different interfaces. For example, "onerror" handles "ErrorEvent"
907926
// normally, but in "SVGSVGElement" it handles "SVGError" event instead.
908927
const eType = p.eventHandler
909928
? getEventTypeInInterface(p.eventHandler!, i)
910929
: "Event";
911-
pType = `(${emitEventHandlerThis(prefix, i)}ev: ${eType}) => any`;
930+
let typeStr = `(${emitEventHandlerThis(prefix, i)}ev: ${eType}) => any`;
912931
if (typeof p.type === "string" && !p.type.endsWith("NonNull")) {
913-
pType = `(${pType}) | null`;
932+
typeStr = `(${typeStr}) | null`;
914933
}
915-
} else {
916-
pType = convertDomTypeToTsType(p);
934+
pForType = { ...p, overrideType: typeStr };
917935
}
918-
if (p.optional) {
919-
pType += " | undefined";
936+
if (pForType.optional) {
937+
pForType = {
938+
...pForType,
939+
additionalTypes: [...(pForType.additionalTypes ?? []), "undefined"],
940+
};
920941
}
942+
const pType = convertDomTypeToTsType(pForType);
943+
921944
const propertyName = p.name.includes("-") ? `"${p.name}"` : p.name;
922945
const optionalModifier = !p.optional || prefix ? "" : "?";
923946
const canPutForward =
@@ -934,10 +957,14 @@ export function emitWebIdl(
934957
if (!forwardingProperty) {
935958
throw new Error("Couldn't find [PutForwards]");
936959
}
937-
let setterType = `${convertDomTypeToTsType(forwardingProperty)}`;
938-
if (!compilerBehavior.allowUnrelatedSetterType) {
939-
setterType += ` | ${pType}`;
940-
}
960+
const setterType = convertDomTypeToTsType(
961+
compilerBehavior.allowUnrelatedSetterType
962+
? forwardingProperty
963+
: {
964+
...forwardingProperty,
965+
type: [forwardingProperty, pForType],
966+
},
967+
);
941968
printer.printLine(
942969
`set ${propertyName}${optionalModifier}(${p.putForwards}: ${setterType});`,
943970
);
@@ -1580,10 +1607,14 @@ export function emitWebIdl(
15801607
.sort(compareName)
15811608
.forEach((m) => {
15821609
emitComments(m, printer.printLine);
1583-
let type = convertDomTypeToTsType(m);
1584-
if (!m.required && !type.split(" | ").includes("undefined")) {
1585-
type += " | undefined";
1586-
}
1610+
const type = convertDomTypeToTsType(
1611+
m.required
1612+
? m
1613+
: {
1614+
...m,
1615+
additionalTypes: [...(m.additionalTypes ?? []), "undefined"],
1616+
},
1617+
);
15871618
printer.printLine(`${m.name}${m.required ? "" : "?"}: ${type};`);
15881619
});
15891620
}

0 commit comments

Comments
 (0)