Skip to content

Commit

Permalink
fix: map filter allow nil results in strict mode, fixes #647
Browse files Browse the repository at this point in the history
  • Loading branch information
harttle committed Aug 23, 2023
1 parent 942944e commit 45adbd7
Show file tree
Hide file tree
Showing 5 changed files with 16 additions and 5 deletions.
4 changes: 2 additions & 2 deletions src/context/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,11 @@ export class Context {
public getFromScope (scope: unknown, paths: PropertyKey[] | string): IterableIterator<unknown> {
return toValueSync(this._getFromScope(scope, paths))
}
public * _getFromScope (scope: unknown, paths: PropertyKey[] | string): IterableIterator<unknown> {
public * _getFromScope (scope: unknown, paths: PropertyKey[] | string, strictVariables = this.strictVariables): IterableIterator<unknown> {
if (isString(paths)) paths = paths.split('.')
for (let i = 0; i < paths.length; i++) {
scope = yield readProperty(scope as object, paths[i], this.ownPropertyOnly)
if (this.strictVariables && isUndefined(scope)) {
if (strictVariables && isUndefined(scope)) {
throw new InternalUndefinedVariableError((paths as string[]).slice(0, i + 1).join!('.'))
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/filters/array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export const size = (v: string | any[]) => (v && v.length) || 0
export function * map (this: FilterImpl, arr: Scope[], property: string): IterableIterator<unknown> {
const results = []
for (const item of toArray(toValue(arr))) {
results.push(yield this.context._getFromScope(item, stringify(property).split('.')))
results.push(yield this.context._getFromScope(item, stringify(property), false))
}
return results
}
Expand Down
5 changes: 4 additions & 1 deletion src/template/filter.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ describe('filter', function () {
it('should render a simple filter', async function () {
expect(await toPromise(new Filter('upcase', (x: string) => x.toUpperCase(), [], liquid).render('foo', ctx))).toBe('FOO')
})

it('should reject promise when filter throws', async function () {
const filter = new Filter('foo', function * () { throw new Error('intended') }, [], liquid)
expect(toPromise(filter.render('foo', ctx))).rejects.toMatch('intended')
})
it('should render filters with argument', async function () {
const two = new NumberToken('2', 0, 1, undefined)
expect(await toPromise(new Filter('add', (a: number, b: number) => a + b, [two], liquid).render(3, ctx))).toBe(5)
Expand Down
2 changes: 1 addition & 1 deletion src/template/filter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@ export class Filter {
if (isKeyValuePair(arg)) argv.push([arg[0], yield evalToken(arg[1], context)])
else argv.push(yield evalToken(arg, context))
}
return this.handler.apply({ context, liquid: this.liquid }, [value, ...argv])
return yield this.handler.apply({ context, liquid: this.liquid }, [value, ...argv])
}
}
8 changes: 8 additions & 0 deletions test/integration/filters/array.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@ describe('filters/array', function () {
const post = { category: 'foo' }
return test('{{post | map: "category"}}', { post }, 'foo')
})
it('should allow nil results in strictVariables mode', function () {
const engine = new Liquid({ strictVariables: true })
const ctx = {
posts: [{ category: 'foo' }, { title: 'bar' }]
}
const result = engine.parseAndRenderSync('{{posts | map: "category" | json}}', ctx)
expect(result).toEqual('["foo",null]')
})
it('should support nested property', function () {
const tpl = '{{ arr | map: "name.first" | join }}'
const a = { name: { first: 'Alice' } }
Expand Down

0 comments on commit 45adbd7

Please sign in to comment.