Skip to content

Commit 1dc7376

Browse files
feat: add tests for duplicate toString detection and multi-return getters with disallowed identifiers
1 parent f8ad9b9 commit 1dc7376

2 files changed

Lines changed: 29 additions & 3 deletions

File tree

libs/ast/src/__tests__/rules.spec.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,33 @@ describe('Validation Rules', () => {
233233
expect(result.valid).toBe(true);
234234
});
235235

236+
it('should detect duplicate toString where last occurrence wins', async () => {
237+
const rule = new DisallowedIdentifierRule({ disallowed: ['constructor'] });
238+
const validator = new JSAstValidator([rule]);
239+
240+
const result = await validator.validate('obj[{toString: () => "safe", toString: () => "constructor"}]', {
241+
rules: { 'disallowed-identifier': true },
242+
});
243+
expect(result.valid).toBe(false);
244+
expect(result.issues[0].code).toBe('DISALLOWED_IDENTIFIER');
245+
expect(result.issues[0].data?.['identifier']).toBe('constructor');
246+
});
247+
248+
it('should detect multi-return getter with disallowed identifier in later return', async () => {
249+
const rule = new DisallowedIdentifierRule({ disallowed: ['constructor'] });
250+
const validator = new JSAstValidator([rule]);
251+
252+
const result = await validator.validate(
253+
"obj[{get toString(){ if(true) return () => 'x'; return () => 'constructor' }}]",
254+
{
255+
rules: { 'disallowed-identifier': true },
256+
},
257+
);
258+
expect(result.valid).toBe(false);
259+
expect(result.issues[0].code).toBe('DISALLOWED_IDENTIFIER');
260+
expect(result.issues[0].data?.['identifier']).toBe('constructor');
261+
});
262+
236263
it('should allow safe template literal', async () => {
237264
const rule = new DisallowedIdentifierRule({ disallowed: ['constructor'] });
238265
const validator = new JSAstValidator([rule]);

libs/ast/src/rules/coercion-utils.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@ function resolveCoercionProperty(prop: any): string | null {
8989
if (inner !== null) return inner;
9090
}
9191
}
92-
break;
9392
}
9493
}
9594
}
@@ -133,9 +132,9 @@ export function tryGetObjectCoercedString(node: any): string | null {
133132
keyName = prop.key.value;
134133
}
135134

136-
if (keyName === 'toString' && !toStringProp) {
135+
if (keyName === 'toString') {
137136
toStringProp = prop;
138-
} else if (keyName === 'valueOf' && !valueOfProp) {
137+
} else if (keyName === 'valueOf') {
139138
valueOfProp = prop;
140139
}
141140
}

0 commit comments

Comments
 (0)