Skip to content

Commit 68387c3

Browse files
committed
fix: "filter is not a function" for uniq
1 parent 2d59cff commit 68387c3

File tree

5 files changed

+22
-14
lines changed

5 files changed

+22
-14
lines changed

src/context/context.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { Drop } from '../drop/drop'
33
import { __assign } from 'tslib'
44
import { NormalizedFullOptions, defaultOptions, RenderOptions } from '../liquid-options'
55
import { Scope } from './scope'
6-
import { isArray, isNil, isUndefined, isString, isFunction, toLiquid, InternalUndefinedVariableError, toValueSync, isObject, Limiter } from '../util'
6+
import { hasOwnProperty, isArray, isNil, isUndefined, isString, isFunction, toLiquid, InternalUndefinedVariableError, toValueSync, isObject, Limiter } from '../util'
77

88
type PropertyKey = string | number;
99

@@ -133,7 +133,7 @@ export function readProperty (obj: Scope, key: PropertyKey, ownPropertyOnly: boo
133133
return value
134134
}
135135
export function readJSProperty (obj: Scope, key: PropertyKey, ownPropertyOnly: boolean) {
136-
if (ownPropertyOnly && !Object.hasOwnProperty.call(obj, key) && !(obj instanceof Drop)) return undefined
136+
if (ownPropertyOnly && !hasOwnProperty.call(obj, key) && !(obj instanceof Drop)) return undefined
137137
return obj[key]
138138
}
139139

@@ -148,7 +148,7 @@ function readLast (obj: Scope) {
148148
}
149149

150150
function readSize (obj: Scope) {
151-
if (obj.hasOwnProperty('size') || obj['size'] !== undefined) return obj['size']
151+
if (hasOwnProperty.call(obj, 'size') || obj['size'] !== undefined) return obj['size']
152152
if (isArray(obj) || isString(obj)) return obj.length
153153
if (typeof obj === 'object') return Object.keys(obj).length
154154
}

src/filters/array.ts

+3-8
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { toArray, argumentsToValue, toValue, stringify, caseInsensitiveCompare, isArray, isNil, last as arrayLast, hasOwnProperty } from '../util'
1+
import { toArray, argumentsToValue, toValue, stringify, caseInsensitiveCompare, isArray, isNil, last as arrayLast } from '../util'
22
import { equals, evalToken, isTruthy } from '../render'
33
import { Value, FilterImpl } from '../template'
44
import { Tokenizer } from '../parser'
@@ -187,14 +187,9 @@ export function * find_exp<T extends object> (this: FilterImpl, arr: T[], itemNa
187187
}
188188

189189
export function uniq<T> (this: FilterImpl, arr: T[]): T[] {
190-
arr = toValue(arr)
190+
arr = toArray(arr)
191191
this.context.memoryLimit.use(arr.length)
192-
const u = {}
193-
return (arr || []).filter(val => {
194-
if (hasOwnProperty.call(u, String(val))) return false
195-
u[String(val)] = true
196-
return true
197-
})
192+
return [...new Set(arr)]
198193
}
199194

200195
export function sample<T> (this: FilterImpl, v: T[] | string, count = 1): T | string | (T | string)[] {

src/util/limiter.ts

+3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { assert } from './assert'
2+
import { toNumber } from './underscore'
23

34
export class Limiter {
45
private message: string
@@ -9,10 +10,12 @@ export class Limiter {
910
this.limit = limit
1011
}
1112
use (count: number) {
13+
count = toNumber(count)
1214
assert(this.base + count <= this.limit, this.message)
1315
this.base += count
1416
}
1517
check (count: number) {
18+
count = toNumber(count)
1619
assert(count <= this.limit, this.message)
1720
}
1821
}

src/util/underscore.ts

+5
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ export function toValue (value: any): any {
6666
return (value instanceof Drop && isFunction(value.valueOf)) ? value.valueOf() : value
6767
}
6868

69+
export function toNumber (value: any): number {
70+
value = Number(value)
71+
return isNaN(value) ? 0 : value
72+
}
73+
6974
export function isNumber (value: any): value is number {
7075
return typeof value === 'number'
7176
}

test/e2e/issues.spec.ts

+8-3
Original file line numberDiff line numberDiff line change
@@ -496,9 +496,14 @@ describe('Issues', function () {
496496
expect(() => liquid.parse({} as any)).not.toThrow()
497497
})
498498
it('Unexpected "RenderError: memory alloc limit exceeded" #737', () => {
499-
const liquid = new Liquid();
500-
const context = { x: ["a", "b"] };
501-
const template = "{{ x | join: 5 }}"
499+
const liquid = new Liquid()
500+
const context = { x: ['a', 'b'] }
501+
const template = '{{ x | join: 5 }}'
502502
expect(liquid.parseAndRender(template, context)).resolves.toEqual('a5b')
503503
})
504+
it('{{ 123 | uniq }} throws #737', () => {
505+
const liquid = new Liquid()
506+
expect(liquid.parseAndRender('{{ 113 | uniq }}')).resolves.toEqual('113')
507+
expect(liquid.parseAndRender("{{ '113' | uniq }}")).resolves.toEqual('113')
508+
})
504509
})

0 commit comments

Comments
 (0)