From b68701a644978dea44b85966b04ee986505b727a Mon Sep 17 00:00:00 2001 From: uzmoi <63585970+uzmoi@users.noreply.github.com> Date: Tue, 23 Dec 2025 01:16:03 +0900 Subject: [PATCH 1/2] Disallow duplicate key --- src/parser/syntaxes/expressions.ts | 3 +++ test/literals.ts | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/src/parser/syntaxes/expressions.ts b/src/parser/syntaxes/expressions.ts index f0a96cb5..fcc59ff0 100644 --- a/src/parser/syntaxes/expressions.ts +++ b/src/parser/syntaxes/expressions.ts @@ -593,6 +593,9 @@ function parseObject(s: ITokenStream, isStatic: boolean): Ast.Obj { const map = new Map(); while (!s.is(TokenKind.CloseBrace)) { const k = parseObjectKey(s); + if (map.has(k)) { + throw new AiScriptSyntaxError(`Key ${k} is duplicated.`, s.getPos()); + } s.next(); s.expect(TokenKind.Colon); diff --git a/test/literals.ts b/test/literals.ts index cb747b7c..330c82bb 100644 --- a/test/literals.ts +++ b/test/literals.ts @@ -251,6 +251,12 @@ describe('literal', () => { `)).rejects.toThrow(AiScriptSyntaxError); }) + test.concurrent('obj (duplicate key)', async () => { + await expect(() => exe(` + <: { hoge: 1, hoge: 2 } + `)).rejects.toThrow(AiScriptSyntaxError); + }); + test.concurrent('obj (invalid key)', async () => { assert.rejects(() => exe(` <: { From 7126328728ed015b3daedfd679030323d7ef9f1b Mon Sep 17 00:00:00 2001 From: uzmoi <63585970+uzmoi@users.noreply.github.com> Date: Tue, 23 Dec 2025 01:30:14 +0900 Subject: [PATCH 2/2] changelog --- unreleased/dupe-key-to-syntax-error.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 unreleased/dupe-key-to-syntax-error.md diff --git a/unreleased/dupe-key-to-syntax-error.md b/unreleased/dupe-key-to-syntax-error.md new file mode 100644 index 00000000..1fbf5d88 --- /dev/null +++ b/unreleased/dupe-key-to-syntax-error.md @@ -0,0 +1 @@ +- Fix: オブジェクトリテラルでキーの重複がエラーになるように修正