mirror of
https://github.com/hanzoai/next.js.git
synced 2026-09-24 17:00:51 +00:00
fix: handle prototype-colliding segment names in segment explorer trie (#95403)
Fixes: https://github.com/vercel/next.js/issues/95395 ```console let x = {} x['constructor']; // function x['toString']; // function x = Object.create(null); x['constructor']; // undefined x['toString'] // undefined ```
This commit is contained in:
@@ -105,6 +105,85 @@ describe('Segment Explorer', () => {
|
||||
})
|
||||
})
|
||||
|
||||
test('handle segments that collide with Object.prototype members', () => {
|
||||
insertSegmentNode(
|
||||
createSegmentNode({ pagePath: '/constructor/page.js', type: 'page' })
|
||||
)
|
||||
insertSegmentNode(
|
||||
createSegmentNode({ pagePath: '/toString/page.js', type: 'page' })
|
||||
)
|
||||
|
||||
const { result } = renderHook(useSegmentTree)
|
||||
|
||||
expect(result.current).toEqual({
|
||||
children: {
|
||||
'': {
|
||||
children: {
|
||||
constructor: {
|
||||
children: {
|
||||
'page.js': {
|
||||
children: {},
|
||||
value: {
|
||||
pagePath: '/constructor/page.js',
|
||||
type: 'page',
|
||||
boundaryType: null,
|
||||
setBoundaryType: expect.anything(),
|
||||
},
|
||||
},
|
||||
},
|
||||
value: undefined,
|
||||
},
|
||||
toString: {
|
||||
children: {
|
||||
'page.js': {
|
||||
children: {},
|
||||
value: {
|
||||
pagePath: '/toString/page.js',
|
||||
type: 'page',
|
||||
boundaryType: null,
|
||||
setBoundaryType: expect.anything(),
|
||||
},
|
||||
},
|
||||
},
|
||||
value: undefined,
|
||||
},
|
||||
},
|
||||
value: undefined,
|
||||
},
|
||||
},
|
||||
value: undefined,
|
||||
})
|
||||
|
||||
removeSegmentNode(
|
||||
createSegmentNode({ pagePath: '/constructor/page.js', type: 'page' })
|
||||
)
|
||||
|
||||
expect(result.current).toEqual({
|
||||
children: {
|
||||
'': {
|
||||
children: {
|
||||
toString: {
|
||||
children: {
|
||||
'page.js': {
|
||||
children: {},
|
||||
value: {
|
||||
pagePath: '/toString/page.js',
|
||||
type: 'page',
|
||||
boundaryType: null,
|
||||
setBoundaryType: expect.anything(),
|
||||
},
|
||||
},
|
||||
},
|
||||
value: undefined,
|
||||
},
|
||||
},
|
||||
value: undefined,
|
||||
},
|
||||
},
|
||||
value: undefined,
|
||||
})
|
||||
})
|
||||
|
||||
test('remove node in the middle', () => {
|
||||
insertSegmentNode(
|
||||
createSegmentNode({ pagePath: '/a/b/@sidebar/page.js', type: 'page' })
|
||||
|
||||
@@ -62,9 +62,11 @@ function createTrie<Value = string>({
|
||||
getCharacters?: (item: Value) => string[]
|
||||
compare?: (a: Value | undefined, b: Value | undefined) => boolean
|
||||
}): Trie<Value> {
|
||||
// Null-prototype children so segment names that collide with
|
||||
// Object.prototype members (e.g. "constructor", "toString") work correctly.
|
||||
let root: TrieNode<Value> = {
|
||||
value: undefined,
|
||||
children: {},
|
||||
children: Object.create(null),
|
||||
}
|
||||
|
||||
function markUpdated() {
|
||||
@@ -82,7 +84,7 @@ function createTrie<Value = string>({
|
||||
currentNode.children[segment] = {
|
||||
value: undefined,
|
||||
// Skip value for intermediate nodes
|
||||
children: {},
|
||||
children: Object.create(null),
|
||||
}
|
||||
}
|
||||
currentNode = currentNode.children[segment]
|
||||
|
||||
Reference in New Issue
Block a user