From 941dd668feea1240c5777617d4ce1ab3ae120342 Mon Sep 17 00:00:00 2001 From: Tejas Manohar Date: Sat, 27 Jun 2020 18:55:56 -0700 Subject: [PATCH] fix: enumerate Promises (e.g. in for & tablerow) (#237) * fix: enumerate Promise (e.g. in {% for ... %}) Previously, a Promise of an array was not being enumerated in {% for %}, for example. This is misleading since the library handles promises elsewhere (e.g. if you {% assign x = promiseArray %} and then {% for v in x %}, it worked just fine. This PR makes Promises of arrays handled by changing toEnumerable to handle then-ables. This affects other iterators, too, e.g. tablerow, so I put in a test for that as well. --- src/builtin/tags/for.ts | 2 +- src/builtin/tags/tablerow.ts | 2 +- test/integration/builtin/tags/for.ts | 8 ++++++++ test/integration/builtin/tags/tablerow.ts | 10 ++++++++++ 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/builtin/tags/for.ts b/src/builtin/tags/for.ts index 276be8cc2..f68dd03ca 100644 --- a/src/builtin/tags/for.ts +++ b/src/builtin/tags/for.ts @@ -36,7 +36,7 @@ export default { }, render: function * (ctx: Context, emitter: Emitter) { const r = this.liquid.renderer - let collection = toEnumerable(evalToken(this.collection, ctx)) + let collection = toEnumerable(yield evalToken(this.collection, ctx)) if (!collection.length) { yield r.renderTemplates(this.elseTemplates, ctx, emitter) diff --git a/src/builtin/tags/tablerow.ts b/src/builtin/tags/tablerow.ts index 81d167232..41ebd6125 100644 --- a/src/builtin/tags/tablerow.ts +++ b/src/builtin/tags/tablerow.ts @@ -30,7 +30,7 @@ export default { }, render: function * (ctx: Context, emitter: Emitter) { - let collection = toEnumerable(evalToken(this.collection, ctx)) + let collection = toEnumerable(yield evalToken(this.collection, ctx)) const hash = yield this.hash.render(ctx) const offset = hash.offset || 0 const limit = (hash.limit === undefined) ? collection.length : hash.limit diff --git a/test/integration/builtin/tags/for.ts b/test/integration/builtin/tags/for.ts index 0c1cb8e0b..fd82fbd53 100644 --- a/test/integration/builtin/tags/for.ts +++ b/test/integration/builtin/tags/for.ts @@ -20,15 +20,23 @@ describe('tags/for', function () { nullProtoObj: Object.create(null), obj: { foo: 'bar', coo: 'haa' }, alpha: ['a', 'b', 'c'], + promiseArray: Promise.resolve(['a', 'b', 'c']), emptyArray: [] } }) + it('should support array', async function () { const src = '{%for c in alpha%}{{c}}{%endfor%}' const html = await liquid.parseAndRender(src, scope) return expect(html).to.equal('abc') }) + it('should support promise of array', async function () { + const src = '{%for c in promiseArray%}{{c}}{%endfor%}' + const html = await liquid.parseAndRender(src, scope) + return expect(html).to.equal('abc') + }) + it('should support object', async function () { const src = '{%for item in obj%}{{item[0]}},{{item[1]}}-{%else%}b{%endfor%}' const html = await liquid.parseAndRender(src, scope) diff --git a/test/integration/builtin/tags/tablerow.ts b/test/integration/builtin/tags/tablerow.ts index a71ee2e4f..a14830784 100644 --- a/test/integration/builtin/tags/tablerow.ts +++ b/test/integration/builtin/tags/tablerow.ts @@ -14,6 +14,16 @@ describe('tags/tablerow', function () { return expect(html).to.equal(dst) }) + it('should support promises', async function () { + const src = '{% tablerow i in promiseNumbers %}{{ i }}{% endtablerow %}' + const ctx = { + promiseNumbers: Promise.resolve([1,2,3]) + } + const dst = '123' + const html = await liquid.parseAndRender(src, ctx) + return expect(html).to.equal(dst) + }) + it('should support cols', async function () { const src = '{% tablerow i in alpha cols:2 %}{{ i }}{% endtablerow %}' const ctx = {