Skip to content

Commit

Permalink
fix: mergeDeep avoid prototype pollution
Browse files Browse the repository at this point in the history
  • Loading branch information
qwqcode committed Dec 26, 2023
1 parent 9b03736 commit 4cc7618
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 2 deletions.
2 changes: 1 addition & 1 deletion ui/artalk/src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class Context implements ContextApi {
public constructor(conf: ArtalkConfig) {
this.conf = conf

this.$root = (conf.el instanceof Element) ? conf.el : document.createElement('div')
this.$root = conf.el as HTMLElement
this.$root.classList.add('artalk')
this.$root.innerHTML = ''

Expand Down
20 changes: 20 additions & 0 deletions ui/artalk/src/lib/merge-deep.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,23 @@ describe('Prevent in-place modify: mergeDeep(a, b)', () => {
expect(b).toEqual({ a: 1, arr: [1, 2, 3] })
})
})

describe('Merge special types', () => {
const testItem = (name: string, val: any) => {
it(name, () => {
expect(mergeDeep({ a: val }, { b: val })).toEqual({ a: val, b: val })
})
}

const dom = document.createElement('div')
testItem('should can keep dom, not deep recursion', dom)

const fn = () => {}
testItem('should can keep function', fn)

const date = new Date()
testItem('should can keep date', date)

const reg = /abc/
testItem('should can keep regex', reg)
})
7 changes: 6 additions & 1 deletion ui/artalk/src/lib/merge-deep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,15 @@
* @returns New object with merged key/values
*/
export function mergeDeep<T>(...objects: any[]): T {
const isObject = (obj: any) => obj && typeof obj === "object";
const isObject = (obj: any) => obj && typeof obj === "object" && obj.constructor === Object;

return objects.reduce((prev, obj) => {
Object.keys(obj ?? {}).forEach((key) => {
// Avoid prototype pollution
if (key === "__proto__" || key === "constructor" || key === "prototype") {
return
}

const pVal = prev[key]
const oVal = obj[key]

Expand Down
11 changes: 11 additions & 0 deletions ui/artalk/tests/ui-api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,17 @@ describe('Artalk instance', () => {
expect(conf.gravatar, "the gravatar which not in update should keep the same").toEqual(RemoteConf.gravatar)
})

it('should can getEl after config updated (artalk.getEl)', () => {
const target = document.getElementById(ContainerID)
expect(target).not.toBe(null)

const el = artalk.getEl()
expect(el).toBe(target)

const el2 = artalk.getConf().el
expect(el2).toBe(target)
})

it('should can set dark mode (artalk.setDarkMode)', () => {
const el = artalk.getEl()
expect(artalk.getConf().darkMode).toBe(true)
Expand Down

0 comments on commit 4cc7618

Please sign in to comment.