Skip to content

Commit

Permalink
Adds finally, additional try tests (closes #9)
Browse files Browse the repository at this point in the history
  • Loading branch information
ndreynolds committed May 12, 2013
1 parent a41ff43 commit 4e59f05
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 43 deletions.
8 changes: 4 additions & 4 deletions src/eval.c
Original file line number Diff line number Diff line change
Expand Up @@ -685,16 +685,16 @@ try_stmt(js_val *ctx, ast_node *node)

// Try
if (!setjmp(state->jmp))
return fh_eval(ctx, node->e1);
fh_eval(ctx, node->e1);
// Catch
else {
fh_set(ctx, node->e2->e1->sval, fh_get(ctx, "FH_LAST_ERROR"));
return fh_eval(ctx, node->e2->e2);
fh_eval(ctx, node->e2->e2);
}

// Finally
if (node->e3)
fh_eval(ctx, node->e3);
if (node->e3 && node->e3->e1)
fh_eval(ctx, node->e3->e1);

return JSUNDEF();
}
Expand Down
2 changes: 1 addition & 1 deletion src/flathead.c
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ fh_throw(eval_state *state, js_val *error)
longjmp(tmp->jmp, 1);
UNREACHABLE();
}
tmp = state->parent;
tmp = tmp->parent;
}

fprintf(stderr, "%s\n", TO_STR(fh_to_primitive(error, T_STRING))->string.ptr);
Expand Down
4 changes: 2 additions & 2 deletions src/grammar.y
Original file line number Diff line number Diff line change
Expand Up @@ -1119,7 +1119,7 @@ yyerror(const char *s)
{
eval_state *state = fh_new_state(yylloc.first_line, yylloc.first_column);
fh_push_state(state);
// Trim the "syntax error: " prefix so we can use fh_error.
// Trim the "syntax error: " prefix so we can use `fh_throw`.
fh_throw(state, fh_new_error(E_SYNTAX, strlen(s) >= 14 ? s + 14 : s));
}

Expand Down Expand Up @@ -1262,7 +1262,7 @@ main(int argc, char **argv)
fh_print_startup();
while (true) {
// Normally errors cause the program to exit, but we'd like the REPL to
// continue. Use setjmp here and longjmp in `fh_error` to simulate
// continue. Use setjmp here and longjmp in `fh_throw` to simulate
// exception handling.
if (!setjmp(fh->repl_jmp))
DEBUG(fh_eval_file(source, fh->global));
Expand Down
162 changes: 126 additions & 36 deletions test/test_try.js
Original file line number Diff line number Diff line change
@@ -1,39 +1,129 @@
// test_try.js
// -----------

// A few basic tests

try {
console.assert(false);
} catch(e) {
}

try {
throw new Error();
} catch(e) {
}

try {
throw new EvalError('the message');
} catch (e) {
console.assert(e.message === 'the message');
console.assert(e.name === 'EvalError');
console.assert(e instanceof EvalError);
}

try {
throw new EvalError('another message');
} catch (someSpecialName) {
console.assert(someSpecialName.message === 'another message');
}

try {
try {
throw new Error('from inner try');
} catch (e) {
console.assert(e.message === 'from inner try');
throw new Error('from inner catch');
}
} catch (e) {
console.assert(e.message === 'from inner catch');
}
(this.load || require)((this.load ? 'test' : '.') + '/tools/assertions.js');

var assertTriedAndCaught = function(f) {
this.caught = false;
this.tried = false;
f();
console.assert(this.tried && this.caught);
};

var nestedThrow = function() {
(function() {
(function() {
(function() {
throw new Error();
})();
})();
})();
};


test('try statement', function() {

test('with console.assert (natively thrown exception)', function() {
assertTriedAndCaught(function() {
try {
this.tried = true;
console.assert(false);
} catch(e) {
console.assert(this.tried);
this.caught = true;
}
});
});

test('with throw statement', function() {
assertTriedAndCaught(function() {
try {
this.tried = true;
throw new Error();
} catch(e) {
console.assert(this.tried);
this.caught = true;
}
});
});

test('exception identifier bound with error object', function() {
assertTriedAndCaught(function() {
try {
this.tried = true;
throw new EvalError('the message');
} catch (e) {
this.caught = true;
console.assert(e.message === 'the message');
console.assert(e.name === 'EvalError');
console.assert(e instanceof EvalError);
}
});
});

test('custom error messages', function() {
assertTriedAndCaught(function() {
try {
this.tried = true;
throw new EvalError('another message');
} catch (someSpecialName) {
this.caught = true;
console.assert(someSpecialName.message === 'another message');
}
});
});

test('nested try statements', function() {
try {
try {
throw new Error('from inner try');
} catch (e) {
console.assert(e.message === 'from inner try');
throw new Error('from inner catch');
}
} catch (e) {
console.assert(e.message === 'from inner catch');
}
});

test('error thrown from call', function() {
assertTriedAndCaught(function() {
try {
this.tried = true;
nestedThrow();
} catch (e) {
this.caught = true;
}
});
});

test('finally runs last', function() {
var final_ran = false;

assertTriedAndCaught(function() {
try {
this.tried = true;
console.assert(false);
} catch(e) {
this.caught = true;
} finally {
console.assert(this.tried && this.caught);
final_ran = true;
}
});

console.assert(final_ran);
});

test('finally always runs', function() {
final_ran = false;

try {
} catch(e) {
} finally {
final_ran = true;
}

console.assert(final_ran);
});
});

0 comments on commit 4e59f05

Please sign in to comment.