Skip to content

Commit b369ffe

Browse files
committed
Updates
1 parent 65e3ee4 commit b369ffe

2 files changed

Lines changed: 63 additions & 12 deletions

File tree

src/schema/pointer/pointer.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ function AssertCanSet(value: unknown): asserts value is Record<string, unknown>
4242
function AssertIndex(index: string): void {
4343
if (Guard.IsUnsafePropertyKey(index)) throw Error('Pointer contains unsafe property key')
4444
}
45+
function AssertIndices(indices: string[]): void {
46+
for (const index of indices) AssertIndex(index)
47+
}
4548
// ------------------------------------------------------------------
4649
// Indices
4750
// ------------------------------------------------------------------
@@ -99,8 +102,8 @@ export function Get(value: unknown, pointer: string): unknown {
99102
export function Set(value: unknown, pointer: string, next: unknown): unknown {
100103
const indices = Indices(pointer)
101104
AssertNotRoot(indices)
105+
AssertIndices(indices)
102106
const [head, index] = TakeIndexRight(indices)
103-
AssertIndex(index)
104107
const parent = GetIndices(head, value)
105108
AssertCanSet(parent)
106109
parent[index] = next
@@ -113,8 +116,8 @@ export function Set(value: unknown, pointer: string, next: unknown): unknown {
113116
export function Delete(value: unknown, pointer: string): unknown {
114117
const indices = Indices(pointer)
115118
AssertNotRoot(indices)
119+
AssertIndices(indices)
116120
const [head, index] = TakeIndexRight(indices)
117-
AssertIndex(index)
118121
const parent = GetIndices(head, value)
119122
AssertCanSet(parent)
120123
if (Guard.IsArray(parent) && IsNumericIndex(index)) {

test/typebox/runtime/schema/pointer/pointer.ts

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,9 @@ Test('Should Indices 20', () => {
8383
const R = [...Schema.Pointer.Indices('/x/a~1b///')]
8484
Assert.IsEqual(R, ['x', 'a/b', '', '', ''])
8585
})
86-
//-----------------------------------------------
86+
//-------------------------------------------------------------------
8787
// Get
88-
//-----------------------------------------------
88+
//-------------------------------------------------------------------
8989
Test('Should Get 1', () => {
9090
const V = [0, 1, 2, 3]
9191
Assert.IsEqual(Schema.Pointer.Get(V, ''), [0, 1, 2, 3])
@@ -108,9 +108,9 @@ Test('Should Get 2', () => {
108108
Assert.IsEqual(Schema.Pointer.Get(V, '/2/x'), 2)
109109
Assert.IsEqual(Schema.Pointer.Get(V, '/3/x'), 3)
110110
})
111-
//-----------------------------------------------
111+
//-------------------------------------------------------------------
112112
// Delete
113-
//-----------------------------------------------
113+
//-------------------------------------------------------------------
114114
Test('Should Delete 1', () => {
115115
const V = { x: {} }
116116
const R = Schema.Pointer.Delete(V, '/x/x')
@@ -131,9 +131,9 @@ Test('Should Delete 3', () => {
131131
const R = Schema.Pointer.Delete(V, '/100')
132132
Assert.IsEqual(R, [1, 2, 3])
133133
})
134-
//-----------------------------------------------
134+
//-------------------------------------------------------------------
135135
// Has
136-
//-----------------------------------------------
136+
//-------------------------------------------------------------------
137137
Test('Should Has 1', () => {
138138
const V: any = undefined
139139
Assert.IsEqual(Schema.Pointer.Has(V, ''), true)
@@ -154,9 +154,9 @@ Test('Should Has 5', () => {
154154
const V = { x: { y: {} } }
155155
Assert.IsEqual(Schema.Pointer.Has(V, '/x/y/z'), false)
156156
})
157-
//-----------------------------------------------
157+
//-------------------------------------------------------------------
158158
// Throw
159-
//-----------------------------------------------
159+
//-------------------------------------------------------------------
160160
Test('Should throw 1', () => {
161161
const V = {}
162162
Assert.Throws(() => Schema.Pointer.Set(V, '', { x: 1 }))
@@ -169,9 +169,9 @@ Test('Should throw 3', () => {
169169
const V = { x: 1 }
170170
Assert.Throws(() => Schema.Pointer.Set(V, '/x/y', 3))
171171
})
172-
//-----------------------------------------------
172+
//-------------------------------------------------------------------
173173
// Escapes
174-
//-----------------------------------------------
174+
//-------------------------------------------------------------------
175175
Test('Should support get ~0 Schema.Pointer escape', () => {
176176
const V = {
177177
x: { '~': { x: 1 } }
@@ -185,3 +185,51 @@ Test('Should support get ~1 Schema.Pointer escape', () => {
185185
}
186186
Assert.IsEqual(Schema.Pointer.Get(V, '/x/~1'), { x: 1 })
187187
})
188+
//-------------------------------------------------------------------
189+
// Unsafe Property Keys
190+
//-------------------------------------------------------------------
191+
Test('Should return undefined if attempting to Get an unsafe property key', () => {
192+
Assert.IsEqual(Schema.Pointer.Get({}, '/__proto__'), undefined)
193+
Assert.IsEqual(Schema.Pointer.Get({}, '/constructor'), undefined)
194+
Assert.IsEqual(Schema.Pointer.Get({}, '/prototype'), undefined)
195+
})
196+
Test('Should return undefined if attempting to Get a nested unsafe property key', () => {
197+
Assert.IsEqual(Schema.Pointer.Get({ a: {} }, '/a/__proto__'), undefined)
198+
Assert.IsEqual(Schema.Pointer.Get({ a: {} }, '/a/constructor'), undefined)
199+
Assert.IsEqual(Schema.Pointer.Get({ a: {} }, '/a/prototype'), undefined)
200+
})
201+
Test('Should return false if attempting to Has an unsafe property key', () => {
202+
Assert.IsEqual(Schema.Pointer.Has({}, '/__proto__'), false)
203+
Assert.IsEqual(Schema.Pointer.Has({}, '/constructor'), false)
204+
Assert.IsEqual(Schema.Pointer.Has({}, '/prototype'), false)
205+
})
206+
Test('Should return false if attempting to Has a nested unsafe property key', () => {
207+
Assert.IsEqual(Schema.Pointer.Has({ a: {} }, '/a/__proto__'), false)
208+
Assert.IsEqual(Schema.Pointer.Has({ a: {} }, '/a/constructor'), false)
209+
Assert.IsEqual(Schema.Pointer.Has({ a: {} }, '/a/prototype'), false)
210+
})
211+
Test('Should throw if attempting to Set an unsafe property key', () => {
212+
Assert.Throws(() => Schema.Pointer.Set({}, '/__proto__', 1))
213+
Assert.Throws(() => Schema.Pointer.Set({}, '/constructor', 1))
214+
Assert.Throws(() => Schema.Pointer.Set({}, '/prototype', 1))
215+
})
216+
Test('Should throw if attempting to Set a nested unsafe property key', () => {
217+
Assert.Throws(() => Schema.Pointer.Set({ a: {} }, '/a/__proto__', 1))
218+
Assert.Throws(() => Schema.Pointer.Set({ a: {} }, '/a/constructor', 1))
219+
Assert.Throws(() => Schema.Pointer.Set({ a: {} }, '/a/prototype', 1))
220+
})
221+
Test('Should throw if attempting to Delete an unsafe property key', () => {
222+
Assert.Throws(() => Schema.Pointer.Delete({}, '/__proto__'))
223+
Assert.Throws(() => Schema.Pointer.Delete({}, '/constructor'))
224+
Assert.Throws(() => Schema.Pointer.Delete({}, '/prototype'))
225+
})
226+
Test('Should throw if attempting to Delete a nested unsafe property key', () => {
227+
Assert.Throws(() => Schema.Pointer.Delete({ a: {} }, '/a/__proto__'))
228+
Assert.Throws(() => Schema.Pointer.Delete({ a: {} }, '/a/constructor'))
229+
Assert.Throws(() => Schema.Pointer.Delete({ a: {} }, '/a/prototype'))
230+
})
231+
Test('Should not throw for property names that contain but do not equal unsafe names', () => {
232+
Assert.IsEqual(Schema.Pointer.Get({ my_constructor: 1 }, '/my_constructor'), 1)
233+
Assert.IsEqual(Schema.Pointer.Get({ prototypes: 1 }, '/prototypes'), 1)
234+
Assert.IsEqual(Schema.Pointer.Get({ not__proto__: 1 }, '/not__proto__'), 1)
235+
})

0 commit comments

Comments
 (0)