Skip to content
This repository was archived by the owner on Jan 6, 2020. It is now read-only.

Commit 5f675cc

Browse files
committed
Simplify implementation
Rather than trying to catch the errors, wrap the argument such that the test knows that an exception occurred before the assertion was invoked.
1 parent 70e2da7 commit 5f675cc

File tree

4 files changed

+107
-194
lines changed

4 files changed

+107
-194
lines changed

example-output.md

Lines changed: 37 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,21 @@ t.throws(foo())
77
becomes:
88

99
```js
10-
function _avaThrowsHelper(fn, data) {
11-
try {
12-
return fn();
13-
} catch (e) {
14-
var type = typeof e;
15-
16-
if (e !== null && (type === "object" || type === "function")) {
17-
try {
18-
Object.defineProperty(e, "_avaThrowsHelperData", {
19-
value: data
20-
});
21-
} catch (e) {}
22-
}
23-
24-
throw e;
10+
function _avaThrowsHelperStart(t, assertion, file, line) {
11+
if (t._throwsArgStart) {
12+
t._throwsArgStart(assertion, file, line);
2513
}
2614
}
2715

28-
t.throws(_avaThrowsHelper(function () {
29-
return foo();
30-
}, {
31-
line: 1,
32-
column: 9,
33-
source: "foo()",
34-
filename: "some-file.js"
35-
}));
16+
function _avaThrowsHelperEnd(t, arg) {
17+
if (t._throwsArgEnd) {
18+
t._throwsArgEnd();
19+
}
20+
21+
return arg;
22+
}
23+
24+
t.throws((_avaThrowsHelperStart(t, "throws", "some-file.js", 1), _avaThrowsHelperEnd(t, foo())));
3625
```
3726

3827
---
@@ -47,40 +36,22 @@ t.throws(bar());
4736
becomes:
4837

4938
```js
50-
function _avaThrowsHelper(fn, data) {
51-
try {
52-
return fn();
53-
} catch (e) {
54-
var type = typeof e;
55-
56-
if (e !== null && (type === "object" || type === "function")) {
57-
try {
58-
Object.defineProperty(e, "_avaThrowsHelperData", {
59-
value: data
60-
});
61-
} catch (e) {}
62-
}
63-
64-
throw e;
39+
function _avaThrowsHelperStart(t, assertion, file, line) {
40+
if (t._throwsArgStart) {
41+
t._throwsArgStart(assertion, file, line);
42+
}
43+
}
44+
45+
function _avaThrowsHelperEnd(t, arg) {
46+
if (t._throwsArgEnd) {
47+
t._throwsArgEnd();
6548
}
49+
50+
return arg;
6651
}
6752

68-
t.throws(_avaThrowsHelper(function () {
69-
return foo();
70-
}, {
71-
line: 1,
72-
column: 9,
73-
source: "foo()",
74-
filename: "some-file.js"
75-
}));
76-
t.throws(_avaThrowsHelper(function () {
77-
return bar();
78-
}, {
79-
line: 2,
80-
column: 9,
81-
source: "bar()",
82-
filename: "some-file.js"
83-
}));
53+
t.throws((_avaThrowsHelperStart(t, "throws", "some-file.js", 1), _avaThrowsHelperEnd(t, foo())));
54+
t.throws((_avaThrowsHelperStart(t, "throws", "some-file.js", 2), _avaThrowsHelperEnd(t, bar())));
8455
```
8556

8657
---
@@ -108,32 +79,21 @@ t.notThrows(baz())
10879
becomes:
10980

11081
```js
111-
function _avaThrowsHelper(fn, data) {
112-
try {
113-
return fn();
114-
} catch (e) {
115-
var type = typeof e;
116-
117-
if (e !== null && (type === "object" || type === "function")) {
118-
try {
119-
Object.defineProperty(e, "_avaThrowsHelperData", {
120-
value: data
121-
});
122-
} catch (e) {}
123-
}
124-
125-
throw e;
82+
function _avaThrowsHelperStart(t, assertion, file, line) {
83+
if (t._throwsArgStart) {
84+
t._throwsArgStart(assertion, file, line);
85+
}
86+
}
87+
88+
function _avaThrowsHelperEnd(t, arg) {
89+
if (t._throwsArgEnd) {
90+
t._throwsArgEnd();
12691
}
92+
93+
return arg;
12794
}
12895

129-
t.notThrows(_avaThrowsHelper(function () {
130-
return baz();
131-
}, {
132-
line: 1,
133-
column: 12,
134-
source: "baz()",
135-
filename: "some-file.js"
136-
}));
96+
t.notThrows((_avaThrowsHelperStart(t, "notThrows", "some-file.js", 1), _avaThrowsHelperEnd(t, baz())));
13797
```
13898

13999
---

index.js

Lines changed: 44 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,85 +1,70 @@
11
'use strict';
2-
var t = require('babel-types');
3-
var template = require('babel-template');
42

5-
var wrapWithHelper = template([
6-
'HELPER_ID(function () {',
7-
' return EXP;',
8-
'}, {',
9-
' line: LINE,',
10-
' column: COLUMN,',
11-
' source: SOURCE,',
12-
' filename: FILE',
13-
'});'
14-
].join('\n'));
3+
module.exports = babelCore => {
4+
const t = babelCore.types;
5+
const wrapArg = babelCore.template('(START(t, ASSERTION, FILE, LINE), END(t, ARG))');
6+
const helpers = babelCore.template(`function START(t, assertion, file, line) {
7+
if (t._throwsArgStart) {
8+
t._throwsArgStart(assertion, file, line);
9+
}
10+
}
11+
12+
function END(t, arg) {
13+
if (t._throwsArgEnd) {
14+
t._throwsArgEnd();
15+
}
1516
16-
var buildHelper = template([
17-
'function HELPER_ID(fn, data) {',
18-
' try {',
19-
' return fn();',
20-
' } catch (e) {',
21-
' var type = typeof e;',
22-
' if (e !== null && (type === "object" || type === "function")) {',
23-
' try {',
24-
' Object.defineProperty(e, "_avaThrowsHelperData", {',
25-
' value: data',
26-
' });',
27-
' } catch (e) {}',
28-
' }',
29-
' throw e;',
30-
' }',
31-
'}'
32-
].join('\n'));
17+
return arg;
18+
}`);
3319

34-
var assertionVisitor = {
35-
CallExpression: function (path, state) {
36-
if (isThrowsMember(path.get('callee'))) {
37-
var arg0 = path.node.arguments[0];
20+
const assertionVisitor = {
21+
CallExpression(path, state) {
22+
const callee = path.get('callee');
23+
if (!callee.isMemberExpression() || !callee.get('object').isIdentifier({name: 't'}) || !callee.get('property').isIdentifier()) {
24+
return;
25+
}
3826

27+
const assertion = callee.get('property').get('name').node;
28+
if (assertion !== 'throws' && assertion !== 'notThrows') {
29+
return;
30+
}
31+
32+
const arg0 = path.node.arguments[0];
3933
if (!(arg0 && arg0.loc && (typeof arg0.start === 'number') && (typeof arg0.end === 'number'))) {
4034
return;
4135
}
4236

43-
path.node.arguments[0] = wrapWithHelper({
44-
HELPER_ID: t.identifier(this.avaThrowHelper()),
45-
EXP: arg0,
46-
LINE: t.numericLiteral(arg0.loc.start.line),
47-
COLUMN: t.numericLiteral(arg0.loc.start.column),
48-
SOURCE: t.stringLiteral(state.file.code.substring(arg0.start, arg0.end)),
49-
FILE: t.stringLiteral(state.file.opts.filename)
50-
}).expression;
37+
// Wrap the argument expression, so that the stack trace of the assertion
38+
// isn't affected.
39+
path.node.arguments[0] = wrapArg(Object.assign({
40+
ARG: arg0,
41+
ASSERTION: t.stringLiteral(assertion),
42+
FILE: t.stringLiteral(state.file.opts.filename),
43+
LINE: t.numericLiteral(arg0.loc.start.line)
44+
}, this.installHelper())).expression;
5145
}
52-
}
53-
};
46+
};
5447

55-
module.exports = function () {
5648
return {
5749
visitor: {
58-
Program: function (path, state) {
59-
var HELPER_ID = path.scope.generateUid('avaThrowsHelper');
60-
var created = false;
50+
Program(path, state) {
51+
const START = t.identifier(path.scope.generateUid('avaThrowsHelperStart'));
52+
const END = t.identifier(path.scope.generateUid('avaThrowsHelperEnd'));
53+
const helperIdentifiers = {START, END};
6154

55+
let created = false;
6256
path.traverse(assertionVisitor, {
63-
avaThrowHelper: function () {
57+
installHelper() {
6458
if (!created) {
6559
created = true;
66-
path.unshiftContainer('body', buildHelper({
67-
HELPER_ID: t.identifier(HELPER_ID)
68-
}));
60+
path.unshiftContainer('body', helpers(helperIdentifiers));
6961
}
7062

71-
return HELPER_ID;
63+
return helperIdentifiers;
7264
},
7365
file: state.file
7466
});
7567
}
7668
}
7769
};
7870
};
79-
80-
function isThrowsMember(path) {
81-
return path.isMemberExpression() && path.get('object').isIdentifier({name: 't'}) && (
82-
path.get('property').isIdentifier({name: 'throws'}) ||
83-
path.get('property').isIdentifier({name: 'notThrows'})
84-
);
85-
}

package.json

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,6 @@
2727
"assertion",
2828
"throws"
2929
],
30-
"dependencies": {
31-
"babel-template": "^6.7.0",
32-
"babel-types": "^6.7.2"
33-
},
3430
"devDependencies": {
3531
"ava": "^0.18.2",
3632
"babel-core": "^6.7.5",

0 commit comments

Comments
 (0)