Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

cfg: make for in loops work with asyncify

  • Loading branch information...
commit 4356c827326cb650050a0af72833453b6f382489 1 parent 75636c2
@indutny authored
Showing with 63 additions and 12 deletions.
  1. +35 −2 lib/spoon/cfg.js
  2. +6 −8 lib/spoon/renderer.js
  3. +22 −2 test/asyncify-test.js
View
37 lib/spoon/cfg.js
@@ -992,22 +992,55 @@ Cfg.prototype.visitFor = function visitFor(ast) {
};
Cfg.prototype.visitForIn = function visitFor(ast) {
- var left = ast.left;
+ var left = ast.left,
+ right = ast.right;
if (left.type === 'VariableDeclaration') {
this.visit(left);
left = left.declarations[0].id;
}
+ var leftName = left.name;
+ left = this.visit(left);
+ right = this.visit(right);
+
+ var props = this.add('getprops', [ right ]),
+ iterator = '__$fi' + props.id;
+
+ // Declare iterator
+ this.currentRoot.prepend('var', [ iterator ]);
+ this.add('set', [ '=', iterator, this.add('literal', [ 0 ]) ]);
+
return this.enterLoop(function(end) {
var start = this.current,
body = this.createBlock();
- this.branch('forin', [this.visit(left), this.visit(ast.right)], body, end);
+ this.breakInfo.update = {
+ type: 'UpdateExpression',
+ operator: '++',
+ prefix: false,
+ argument: { type: 'Identifier', name: iterator }
+ };
+
+ var propCount = this.add('getprop', [ props, this.visit({
+ type: 'Literal',
+ value: 'length'
+ }) ]);
+ var test = this.add('binop', [ '<',
+ this.add('get', [ iterator ]),
+ propCount ]);
+
+ // Iterate through properties and set left according to current property
+ this.branch('while', [test], body, end);
start.end();
this.setCurrentBlock(body);
+ this.add('set', [ '=',
+ leftName,
+ this.add('getprop', [ props,
+ this.add('get', [ iterator ]) ]) ]);
this.visit(ast.body);
+ this.visit(this.breakInfo.update);
});
};
View
14 lib/spoon/renderer.js
@@ -167,14 +167,14 @@ Renderer.prototype.renderInstruction = function renderInstruction(instr) {
fn = this.renderMethod;
} else if (t === 'getprop') {
fn = this.renderGetprop;
+ } else if (t === 'getprops') {
+ fn = this.renderGetprops;
} else if (t === 'if') {
fn = this.renderIf;
} else if (t === 'logical') {
fn = this.renderIf;
} else if (t === 'while') {
fn = this.renderWhile;
- } else if (t === 'forin') {
- fn = this.renderForIn;
} else if (t === 'break') {
fn = this.renderBreak;
} else if (t === 'sbreak') {
@@ -309,6 +309,10 @@ Renderer.prototype.renderGetprop = function renderGetprop(args) {
return ['sub', args[0], args[1]];
};
+Renderer.prototype.renderGetprops = function renderGetprops(args) {
+ return ['call', ['dot', ['name', 'Object'], 'keys'], [ args[0] ]];
+};
+
Renderer.prototype.renderIf = function renderIf(args) {
var slots = [ [], [] ],
ast = ['if', args[0]].concat(slots.map(function(slot) {
@@ -326,12 +330,6 @@ Renderer.prototype.renderWhile = function renderWhile(args) {
return ['while', args[0], ['block', slot]];
};
-Renderer.prototype.renderForIn = function renderForIn(args) {
- var slot = [];
- this.addSlots([ slot ]);
- return ['for-in', args[0], args[0], args[1], ['block', slot]];
-};
-
Renderer.prototype.renderBreak = function renderBreak(args) {
return ['break'];
};
View
24 test/asyncify-test.js
@@ -13,6 +13,7 @@ describe('Spoon', function() {
var out = spoon.render(cfg);
var code = uglify.uglify.gen_code(out, { beautify: true });
+ console.log(code);
var res,
once = false;
@@ -71,7 +72,7 @@ describe('Spoon', function() {
r = assert.equal(r, 124);
});
- it('should asyncify call in for', function() {
+ it('should asyncify call in for loop', function() {
var r = test(function fn(__$callback) {
"enable spoon";
function async(a, b, callback) {
@@ -88,7 +89,7 @@ describe('Spoon', function() {
r = assert.equal(r, 46);
});
- it('should asyncify call in do while', function() {
+ it('should asyncify call in do while loop', function() {
var r = test(function fn(__$callback) {
"enable spoon";
function async(a, b, callback) {
@@ -107,5 +108,24 @@ describe('Spoon', function() {
r = assert.equal(r, 56);
});
+
+ it('should asyncify call in for in loop', function() {
+ var r = test(function fn(__$callback) {
+ "enable spoon";
+ function async(a, b, callback) {
+ callback(a + b);
+ }
+
+ var obj = { a : 1, b : 2 };
+
+ for (var i in obj) {
+ var x = async(obj[i], x || 0);
+ }
+
+ return x + 1;
+ });
+
+ r = assert.equal(r, 4);
+ });
});
});
Please sign in to comment.
Something went wrong with that request. Please try again.