diff --git a/compiler/ast/ForEachProp.js b/compiler/ast/ForEachProp.js
index 7ae1874eb..b380875e2 100644
--- a/compiler/ast/ForEachProp.js
+++ b/compiler/ast/ForEachProp.js
@@ -8,6 +8,8 @@ class ForEachProp extends Node {
this.nameVarName = def.nameVarName;
this.valueVarName = def.valueVarName;
this.in = def.in;
+ this.separator = def.separator;
+ this.statusVarName = def.statusVarName;
this.body = this.makeContainer(def.body);
ok(this.nameVarName, '"nameVarName" is required');
@@ -20,16 +22,45 @@ class ForEachProp extends Node {
var valueVarName = this.valueVarName;
var inExpression = this.in;
var body = this.body;
+ var separator = this.separator;
+ var statusVarName = this.statusVarName;
+
+ if (separator && !statusVarName) {
+ statusVarName = '__loop';
+ }
var builder = codegen.builder;
- let forEachVarName = codegen.addStaticVar('forEachProp', '__helpers.fp');
+ if (statusVarName) {
+ let helperVar = builder.require(builder.literal('marko/runtime/forEachPropStatusVar'));
+ let forEachVarName = codegen.addStaticVar('forEacPropStatusVar', helperVar);
+ let body = this.body;
- return builder.functionCall(forEachVarName, [
- inExpression,
- builder.functionDeclaration(null, [nameVarName, valueVarName], body)
- ]);
+ if (separator) {
+ let isNotLastTest = builder.functionCall(
+ builder.memberExpression(statusVarName, builder.identifier('isLast')),
+ []);
+ isNotLastTest = builder.negate(isNotLastTest);
+
+ body = body.items.concat([
+ builder.ifStatement(isNotLastTest, [
+ builder.text(separator)
+ ])
+ ]);
+ }
+
+ return builder.functionCall(forEachVarName, [
+ inExpression,
+ builder.functionDeclaration(null, [nameVarName, valueVarName, statusVarName], body)
+ ]);
+ } else {
+ let forEachVarName = codegen.addStaticVar('forEachProp', '__helpers.fp');
+ return builder.functionCall(forEachVarName, [
+ inExpression,
+ builder.functionDeclaration(null, [nameVarName, valueVarName], body)
+ ]);
+ }
}
walk(walker) {
diff --git a/runtime/forEachPropStatusVar.js b/runtime/forEachPropStatusVar.js
new file mode 100644
index 000000000..39aca95be
--- /dev/null
+++ b/runtime/forEachPropStatusVar.js
@@ -0,0 +1,32 @@
+function LoopStatus(getLength, isLast, isFirst, getIndex) {
+ this.getLength = getLength;
+ this.isLast = isLast;
+ this.isFirst = isFirst;
+ this.getIndex = getIndex;
+}
+
+module.exports = function forEachPropStatusVar(object, callback) {
+ var keys = Object.keys(object);
+
+ var i = 0;
+ var len = keys.length;
+ var loopStatus = new LoopStatus(
+ function getLength() {
+ return len;
+ },
+ function isLast() {
+ return i === len - 1;
+ },
+ function isFirst() {
+ return i === 0;
+ },
+ function getIndex() {
+ return i;
+ });
+
+ for (; i < len; i++) {
+ var key = keys[i];
+ var value = object[key];
+ callback(key, value, loopStatus);
+ }
+};
\ No newline at end of file
diff --git a/taglibs/core/util/parseFor.js b/taglibs/core/util/parseFor.js
index cfc8c5ad5..d04dc20ab 100644
--- a/taglibs/core/util/parseFor.js
+++ b/taglibs/core/util/parseFor.js
@@ -333,7 +333,9 @@ module.exports = function(str) {
'loopType': loopType,
'nameVarName': nameVarName,
'valueVarName': valueVarName,
- 'in': inExpression
+ 'in': inExpression,
+ 'separator': separatorExpression,
+ 'statusVarName': statusVarName
};
} else if (loopType === 'ForRange') {
return {
diff --git a/test/autotests/render/for-props-separator/expected.html b/test/autotests/render/for-props-separator/expected.html
new file mode 100644
index 000000000..6de235e41
--- /dev/null
+++ b/test/autotests/render/for-props-separator/expected.html
@@ -0,0 +1 @@
+[foo=low],[bar=high]
\ No newline at end of file
diff --git a/test/autotests/render/for-props-separator/template.marko b/test/autotests/render/for-props-separator/template.marko
new file mode 100644
index 000000000..1cf5ad6a5
--- /dev/null
+++ b/test/autotests/render/for-props-separator/template.marko
@@ -0,0 +1 @@
+[${name}=${value}]
\ No newline at end of file
diff --git a/test/autotests/render/for-props-separator/test.js b/test/autotests/render/for-props-separator/test.js
new file mode 100644
index 000000000..c4013b344
--- /dev/null
+++ b/test/autotests/render/for-props-separator/test.js
@@ -0,0 +1 @@
+exports.templateData = {};
diff --git a/test/autotests/render/for-props-status-var-separator/expected.html b/test/autotests/render/for-props-status-var-separator/expected.html
new file mode 100644
index 000000000..3d043d356
--- /dev/null
+++ b/test/autotests/render/for-props-status-var-separator/expected.html
@@ -0,0 +1 @@
+0) [foo=low],1) [bar=high]
\ No newline at end of file
diff --git a/test/autotests/render/for-props-status-var-separator/template.marko b/test/autotests/render/for-props-status-var-separator/template.marko
new file mode 100644
index 000000000..22d3a1f4e
--- /dev/null
+++ b/test/autotests/render/for-props-status-var-separator/template.marko
@@ -0,0 +1 @@
+${loop.getIndex()}) [${name}=${value}]
\ No newline at end of file
diff --git a/test/autotests/render/for-props-status-var-separator/test.js b/test/autotests/render/for-props-status-var-separator/test.js
new file mode 100644
index 000000000..c4013b344
--- /dev/null
+++ b/test/autotests/render/for-props-status-var-separator/test.js
@@ -0,0 +1 @@
+exports.templateData = {};
diff --git a/test/autotests/render/for-props-status-var/expected.html b/test/autotests/render/for-props-status-var/expected.html
new file mode 100644
index 000000000..8dd13e24a
--- /dev/null
+++ b/test/autotests/render/for-props-status-var/expected.html
@@ -0,0 +1 @@
+0) [foo=low]1) [bar=high]
\ No newline at end of file
diff --git a/test/autotests/render/for-props-status-var/template.marko b/test/autotests/render/for-props-status-var/template.marko
new file mode 100644
index 000000000..5c1db9ca6
--- /dev/null
+++ b/test/autotests/render/for-props-status-var/template.marko
@@ -0,0 +1,3 @@
+
+ ${loop.getIndex()}) [${name}=${value}]
+
\ No newline at end of file
diff --git a/test/autotests/render/for-props-status-var/test.js b/test/autotests/render/for-props-status-var/test.js
new file mode 100644
index 000000000..c4013b344
--- /dev/null
+++ b/test/autotests/render/for-props-status-var/test.js
@@ -0,0 +1 @@
+exports.templateData = {};