Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
changeKind: fix
packages:
- "@typespec/compiler"
---

Fix crash when using custom scalar initializer in examples or default values
[API] Fix crash in `serializeValueAsJson` when a custom scalar initializer has no recognized constructor (e.g. `S.i()` with no args). Now returns `undefined` instead of crashing.

2 changes: 1 addition & 1 deletion packages/compiler/src/lib/examples.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ function serializeScalarValueAsJson(

const result = resolveKnownScalar(program, value.scalar);
if (result === undefined) {
return serializeValueAsJson(program, value.value.args[0], value.value.args[0].type);
return undefined;
}

encodeAs = encodeAs ?? result.encodeAs;
Expand Down
22 changes: 22 additions & 0 deletions packages/compiler/test/decorators/examples.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,28 @@ describe("@example", () => {
code: "unassignable",
});
});

it("returns undefined for custom scalar with no-argument initializer", async () => {
const { program, examples, target } = await getExamplesFor(`
@example(test.i())
@test scalar test {
init i();
}
`);
expect(examples).toHaveLength(1);
expect(serializeValueAsJson(program, examples[0].value, target)).toBeUndefined();
});

it("returns undefined for custom scalar with string-argument initializer", async () => {
const { program, examples, target } = await getExamplesFor(`
@example(test.name("Shorty"))
@test scalar test {
init name(value: string);
}
`);
expect(examples).toHaveLength(1);
expect(serializeValueAsJson(program, examples[0].value, target)).toBeUndefined();
});
});

describe("enum", () => {
Expand Down
32 changes: 30 additions & 2 deletions packages/openapi3/test/models.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ worksFor(supportedVersions, ({ diagnoseOpenApiFor, oapiForModel, openApiFor }) =
});
});

it("scalar used as a default value", async () => {
it("scalar with unknown constructor used as a default value produces no default and no diagnostic", async () => {
const res = await oapiForModel(
"Pet",
`
Expand All @@ -272,7 +272,35 @@ worksFor(supportedVersions, ({ diagnoseOpenApiFor, oapiForModel, openApiFor }) =
`,
);

expect(res.schemas.Pet.properties.name.default).toEqual("Shorty");
expect(res.schemas.Pet.properties.name.default).toBeUndefined();
});

it("scalar with no-argument initializer used as a default value does not crash", async () => {
const res = await oapiForModel(
"M",
`
scalar S { init i(); }

model M { p: S = S.i(); }
`,
);

expect(res.schemas.M.properties.p.default).toBeUndefined();
});

it("known scalar constructors used as default values produce correct defaults", async () => {
const res = await oapiForModel(
"Foo",
`
model Foo {
int32Prop: int32 = int32(12);
stringProp: string = string("this is the string value");
}
`,
);

expect(res.schemas.Foo.properties.int32Prop.default).toEqual(12);
expect(res.schemas.Foo.properties.stringProp.default).toEqual("this is the string value");
});

it("encode know scalar as a default value", async () => {
Expand Down
Loading