Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

api: use better traversal, hide details

  • Loading branch information...
commit 030d6ef49f3568d73cdeb85de7f0feba98aa5d89 1 parent d2eaa3d
@indutny authored
Showing with 35 additions and 29 deletions.
  1. +1 −1  README.md
  2. +34 −28 lib/spoon/api.js
View
2  README.md
@@ -1,6 +1,6 @@
# Spoon
-Coming soon...
+Continuation passing style for javascript.
### License
View
62 lib/spoon/api.js
@@ -18,35 +18,41 @@ api.render = function render(cfg) {
};
function patch(ast, decl, callback) {
- var lastFn = null;
- function traverse(ast) {
- if (Array.isArray(ast)) return ast.forEach(traverse);
-
- if (typeof ast !== 'object' || ast === null || !ast.type) return;
- var restore;
-
- if (ast.type === 'Literal') {
- if (ast.value === decl && lastFn) {
- lastFn.body = callback(lastFn).body[0].body;
+ var fn = null,
+ body = null,
+ stack = [];
+
+ escodegen.traverse(ast, {
+ enter: function(ast) {
+ if (ast.type === 'Literal') {
+ if (ast.value === decl && fn) {
+ body = callback(fn).body;
+ }
+ return;
+ } else if (ast.type === 'FunctionDeclaration' ||
+ ast.type ===' FunctionExpression') {
+ stack.push({
+ fn: fn,
+ body: body
+ });
+ fn = ast;
+ }
+ },
+ leave: function(ast) {
+ if (ast === fn) {
+ if (body !== null) ast.body = body;
+
+ // Restore previous position
+ var onstack = stack.pop();
+ if (onstack) {
+ fn = onstack.fn;
+ body = onstack.body;
+ }
}
- return;
- } else if (ast.type === 'FunctionDeclaration' ||
- ast.type ===' FunctionExpression') {
- restore = lastFn;
- lastFn = ast;
}
+ });
- // Very naive traverse
- Object.keys(ast).forEach(function(key) {
- // Ignore obvious keys
- if (key === 'type' || key === 'prefix' || key === 'operator') return;
- traverse(ast[key]);
- });
-
- if (restore !== undefined) lastFn = restore;
- }
-
- traverse(ast);
+ return ast;
};
api.preprocess = function preprocess(code, options, callback) {
@@ -55,7 +61,7 @@ api.preprocess = function preprocess(code, options, callback) {
var ast = esprima.parse(code, options.esprima);
if (options.declaration) {
- patch(ast, options.declaration, function replace(ast) {
+ ast = patch(ast, options.declaration, function replace(ast) {
var cfg = api.spoon.construct(ast);
if (callback) callback(cfg);
@@ -64,7 +70,7 @@ api.preprocess = function preprocess(code, options, callback) {
// A big fat hack here, but I need to get Esprima AST to replace it.
return esprima.parse(uglify.uglify.gen_code(ast, options.uglify),
- options.esprima);
+ options.esprima).body[0];
});
// And this is a hack too
Please sign in to comment.
Something went wrong with that request. Please try again.