Skip to content

Commit 8039e71

Browse files
authored
fix(core-base): key paths containing javascript built-ins are handled inconsistently (#2403)
* fix(core-base): key paths containing javascript built-ins are handled inconsistently * fix: format
1 parent 638f0a5 commit 8039e71

2 files changed

Lines changed: 39 additions & 2 deletions

File tree

packages/core-base/src/resolver.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { isFunction, isObject } from '@intlify/shared'
1+
import { hasOwn, isFunction, isObject } from '@intlify/shared'
22
import { AST_NODE_PROPS_KEYS, isMessageAST } from './ast'
33

44
/** @VueI18nGeneral */
@@ -335,7 +335,8 @@ export function resolveValue(obj: unknown, path: Path): PathValue {
335335

336336
// resolve path value
337337
const len = hit.length
338-
let last = obj
338+
339+
let last: any = obj
339340
let i = 0
340341
while (i < len) {
341342
const key = hit[i]
@@ -350,6 +351,9 @@ export function resolveValue(obj: unknown, path: Path): PathValue {
350351
if (!isObject(last)) {
351352
return null
352353
}
354+
if (!hasOwn(last as object, key)) {
355+
return null
356+
}
353357
const val = last[key]
354358
if (val === undefined) {
355359
return null

packages/core-base/test/resolver.test.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,39 @@ describe('resolveValue', () => {
133133
expect(resolveValue({ 'test.link': 'world' }, 'test.link')).toEqual(null)
134134
})
135135

136+
test('Object.prototype built-in key paths (issue #1838)', () => {
137+
const builtins = [
138+
'constructor',
139+
'hasOwnProperty',
140+
'isPrototypeOf',
141+
'propertyIsEnumerable',
142+
'toLocaleString',
143+
'toString',
144+
'valueOf',
145+
'__proto__'
146+
]
147+
148+
// top-level: builtin name as key with value defined -> should resolve
149+
for (const k of builtins) {
150+
expect(resolveValue({ [k]: 'hi' }, k)).toEqual('hi')
151+
}
152+
153+
// top-level: builtin name as key, NOT defined -> should return null
154+
for (const k of builtins) {
155+
expect(resolveValue({}, k)).toEqual(null)
156+
}
157+
158+
// nested: a.<builtin>.c with value defined -> should resolve
159+
for (const k of builtins) {
160+
expect(resolveValue({ a: { [k]: { c: 'hi' } } }, `a.${k}.c`)).toEqual('hi')
161+
}
162+
163+
// nested: a.<builtin>.c without value -> should return null
164+
for (const k of builtins) {
165+
expect(resolveValue({ a: {} }, `a.${k}.c`)).toEqual(null)
166+
}
167+
})
168+
136169
test('ast', () => {
137170
expect(resolveValue(ast, 'language')).toEqual(ast.language)
138171
expect(resolveValue(ast, 'product')).toEqual(ast.product)

0 commit comments

Comments
 (0)