Skip to content

Instantly share code, notes, and snippets.

@aseemk
Created August 10, 2011 01:12
Show Gist options
  • Save aseemk/1135758 to your computer and use it in GitHub Desktop.
Save aseemk/1135758 to your computer and use it in GitHub Desktop.
Streamline bug: nested switch statements somehow mess up sync flow
# async simulation helper:
async = (_) ->
setTimeout _, 500
# assume we're dealing with a status change event
type = 'event'
kind = 'statusChange'
# assume we initially have no user or target
user = null
target = null
getUser = (_) ->
console.log 'fetching user...'
async _
console.log 'user fetched.'
return {}
getTarget = (_) ->
console.log 'fetching target...'
async _
console.log 'target fetched.'
return {}
METHOD = (_) ->
console.log "BEGIN"
if type is 'comment'
user or= getUser _
target or= getTarget _
else if type is 'event'
if kind is 'statusChange'
user or= getUser _
target or= getTarget _
else if kind is 'follow'
user or= getUser _
target or= getTarget _
console.log "END"
METHOD _
var METHOD, async, getTarget, getUser, kind, target, type, user;
async = function(_) {
return setTimeout(_, 500);
};
type = 'event';
kind = 'statusChange';
user = null;
target = null;
getUser = function(_) {
console.log('fetching user...');
async(_);
console.log('user fetched.');
return {};
};
getTarget = function(_) {
console.log('fetching target...');
async(_);
console.log('target fetched.');
return {};
};
METHOD = function(_) {
console.log("BEGIN");
if (type === 'comment') {
user || (user = getUser(_));
target || (target = getTarget(_));
} else if (type === 'event') {
if (kind === 'statusChange') {
user || (user = getUser(_));
target || (target = getTarget(_));
} else if (kind === 'follow') {
user || (user = getUser(_));
target || (target = getTarget(_));
}
}
return console.log("END");
};
METHOD(_);
BEGIN
fetching user...
user fetched.
fetching target...
target fetched.
END
var __global = typeof global !== 'undefined' ? global : window;
function __cb(_, fn){ var ctx = __global.__context; return function(err, result){ __global.__context = ctx; if (err) return _(err); try { return fn(null, result); } catch (ex) { return __propagate(_, ex); } } }
function __future(fn, args, i){ var done, err, result; var cb = function(e, r){ done = true; err = e, result = r; }; args = Array.prototype.slice.call(args); args[i] = function(e, r){ cb(e, r); }; fn.apply(this, args); return function(_){ if (done) _.call(this, err, result); else cb = _.bind(this); } .bind(this); }
function __propagate(_, err){ try { _(err); } catch (ex) { __trap(ex); } }
function __trap(err){ if (err) { if (__global.__context && __global.__context.errorHandler) __global.__context.errorHandler(err); else console.error("UNCAUGHT EXCEPTION: " + err.message + "\n" + err.stack); } }
(function __main(_) {
var METHOD, async, getTarget, getUser, kind, target, type, user;
/* 2 */ async = function __1(_) {
if (!_) {
return __future(__1, arguments, 0);
}
;
/* 3 */ return setTimeout(_, 500);
};
/* 5 */ type = "event";
/* 6 */ kind = "statusChange";
/* 7 */ user = null;
/* 8 */ target = null;
/* 9 */ getUser = function __2(_) {
if (!_) {
return __future(__2, arguments, 0);
}
;
/* 10 */ console.log("fetching user...");
/* 11 */ return async(__cb(_, function() {
/* 12 */ console.log("user fetched.");
/* 13 */ return _(null, {
});
}));
};
/* 15 */ getTarget = function __3(_) {
if (!_) {
return __future(__3, arguments, 0);
}
;
/* 16 */ console.log("fetching target...");
/* 17 */ return async(__cb(_, function() {
/* 18 */ console.log("target fetched.");
/* 19 */ return _(null, {
});
}));
};
/* 21 */ METHOD = function __4(_) {
if (!_) {
return __future(__4, arguments, 0);
}
;
/* 22 */ console.log("BEGIN");
(function(__break) {
/* 23 */ switch (type) {
/* 24 */ case "comment":
/* 24 */ return (function(_) {
var __1 = user;
/* 25 */ if (__1) {
return _(null, __1);
}
;
return getUser(__cb(_, function(__0, __3) {
/* 25 */ var __2 = (user = __3);
/* 25 */ return _(null, __2);
}));
})(__cb(_, function() {
return (function(_) {
var __2 = target;
/* 26 */ if (__2) {
return _(null, __2);
}
;
return getTarget(__cb(_, function(__0, __4) {
/* 26 */ var __3 = (target = __4);
/* 26 */ return _(null, __3);
}));
})(__cb(_, function() {
return __break();
}));
}));
case "event":
(function(__break) {
/* 28 */ switch (kind) {
/* 28 */ case "statusChange":
return (function(_) {
/* 29 */ var __3 = user;
/* 30 */ if (__3) {
/* 30 */ return _(null, __3);
}
/* 31 */ ;
return getUser(__cb(_, function(__0, __5) {
var __4 = (user = __5);
return _(null, __4);
}));
/* 31 */ })(__cb(_, function() {
/* 31 */ return (function(_) {
var __4 = target;
if (__4) {
return _(null, __4);
}
/* 32 */ ;
return getTarget(__cb(_, function(__0, __6) {
var __5 = (target = __6);
return _(null, __5);
}));
/* 32 */ })(__cb(_, function() {
/* 32 */ return __break();
}));
}));
case "follow":
return (function(_) {
var __5 = user;
if (__5) {
return _(null, __5);
/* 34 */ }
/* 34 */ ;
return getUser(__cb(_, function(__0, __7) {
/* 35 */ var __6 = (user = __7);
return _(null, __6);
}));
})(__cb(_, function() {
return (function(_) {
/* 35 */ var __6 = target;
/* 35 */ if (__6) {
return _(null, __6);
}
;
return getTarget(__cb(_, function(__0, __8) {
/* 36 */ var __7 = (target = __8);
return _(null, __7);
}));
})(__cb(_, function() {
return __break();
/* 36 */ }));
/* 36 */ }));
default:
return __break();
};
})(function() {
return __break();
});
default:
return __break();
};
})(function() {
return _(null, console.log("END"));
});
};
return METHOD(_);
}).call(this, __trap);
# async simulation helper:
async = (_) ->
setTimeout _, 500
# assume we're dealing with a status change event
type = 'event'
kind = 'statusChange'
# assume we initially have no user or target
user = null
target = null
getUser = (_) ->
console.log 'fetching user...'
async _
console.log 'user fetched.'
return {}
getTarget = (_) ->
console.log 'fetching target...'
async _
console.log 'target fetched.'
return {}
METHOD = (_) ->
console.log "BEGIN"
switch type
when 'comment'
user or= getUser _
target or= getTarget _
when 'event'
switch kind
when 'statusChange'
user or= getUser _
target or= getTarget _
when 'follow'
user or= getUser _
target or= getTarget _
console.log "END"
METHOD _
var METHOD, async, getTarget, getUser, kind, target, type, user;
async = function(_) {
return setTimeout(_, 500);
};
type = 'event';
kind = 'statusChange';
user = null;
target = null;
getUser = function(_) {
console.log('fetching user...');
async(_);
console.log('user fetched.');
return {};
};
getTarget = function(_) {
console.log('fetching target...');
async(_);
console.log('target fetched.');
return {};
};
METHOD = function(_) {
console.log("BEGIN");
switch (type) {
case 'comment':
user || (user = getUser(_));
target || (target = getTarget(_));
break;
case 'event':
switch (kind) {
case 'statusChange':
user || (user = getUser(_));
target || (target = getTarget(_));
break;
case 'follow':
user || (user = getUser(_));
target || (target = getTarget(_));
}
}
return console.log("END");
};
METHOD(_);
BEGIN
fetching user...
END
user fetched.
fetching target...
target fetched.
END
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment