1 | var util = require('util');
|
2 | var traverse = require('../traverse');
|
3 | var helpers = require('../helpers');
|
4 | var BinaryExpression = require('./BinaryExpression');
|
5 | var BlockStatement = require('./BlockStatement');
|
6 | var CatchClause = require('./CatchClause');
|
7 | var CallExpression = require('./CallExpression');
|
8 | var ExpressionStatement = require('./ExpressionStatement');
|
9 | var FunctionExpression = require('./FunctionExpression');
|
10 | var Identifier = require('./Identifier');
|
11 | var IfStatement = require('./IfStatement');
|
12 | var ReturnStatement = require('./ReturnStatement');
|
13 |
|
14 | var TryStatement = module.exports = function(block, handlers, finalizer) {
|
15 | this.type = 'TryStatement';
|
16 | this.block = block;
|
17 | this.handlers = handlers;
|
18 | this.finalizer = finalizer;
|
19 | if (!util.isArray(this.handlers)) {
|
20 | this.handlers = [this.handlers];
|
21 | }
|
22 | if (!this.finalizer) {
|
23 | this.finalizer = null;
|
24 | }
|
25 | this.async = false;
|
26 | };
|
27 |
|
28 | TryStatement.prototype.normalize = function (place) {
|
29 | this.block.normalize();
|
30 | for (var i = 0; i < this.handlers.length; i++) {
|
31 | this.handlers[i].normalize();
|
32 | }
|
33 | if (this.finalizer) {
|
34 | this.finalizer.normalize();
|
35 | }
|
36 | place.push(this);
|
37 | };
|
38 |
|
39 | TryStatement.prototype.transform = function (place) {
|
40 | var innerPlace = this.block.transform(place);
|
41 |
|
42 |
|
43 | var handler = this.handlers[0];
|
44 |
|
45 | if (handler) {
|
46 | var handlerPlace = handler.transform(place);
|
47 | }
|
48 |
|
49 |
|
50 | if (!this.block.async && ((handler && !handler.async) || !handler) ) {
|
51 | place.push(this);
|
52 | return innerPlace;
|
53 | }
|
54 |
|
55 | var contIdentifier = new Identifier(helpers.continuationIdentifier);
|
56 | var errIdentifier = new Identifier(helpers.errName);
|
57 | var cont = new ExpressionStatement(new CallExpression(contIdentifier));
|
58 | var breakCont = new ExpressionStatement(new CallExpression(contIdentifier, errIdentifier));
|
59 |
|
60 | if (this.block.async) {
|
61 |
|
62 | innerPlace.push(cont);
|
63 |
|
64 |
|
65 | var tryFunction = new FunctionExpression(null, [contIdentifier], this.block);
|
66 |
|
67 |
|
68 | traverse(tryFunction, function (node) {
|
69 | if (node.type === 'FunctionExpression') {
|
70 | var innerTry = new TryStatement(node.body, new CatchClause(
|
71 | errIdentifier,
|
72 | null,
|
73 | new BlockStatement(breakCont)
|
74 | ));
|
75 | node.body = new BlockStatement(innerTry);
|
76 | }
|
77 | return node;
|
78 | });
|
79 |
|
80 |
|
81 | var judgeIfException = new IfStatement(
|
82 | new BinaryExpression('!==', handler.param, new Identifier('undefined')),
|
83 | handler.body,
|
84 | null
|
85 | );
|
86 | var handlerFunction = new FunctionExpression(
|
87 | null,
|
88 | [handler.param],
|
89 | new BlockStatement(judgeIfException)
|
90 | );
|
91 | var tryCatch = new ExpressionStatement(new CallExpression(tryFunction, handlerFunction));
|
92 | } else {
|
93 | var tryCatch = this;
|
94 | }
|
95 |
|
96 | if (handler) {
|
97 | if (handler.async) {
|
98 |
|
99 | var continuationFunction = new FunctionExpression(null, [], new BlockStatement());
|
100 | var catchFunction = new FunctionExpression(
|
101 | null,
|
102 | [contIdentifier],
|
103 | new BlockStatement(tryCatch)
|
104 | );
|
105 |
|
106 | var tryCatchContinuation = new ExpressionStatement(new CallExpression(
|
107 | catchFunction,
|
108 | [continuationFunction]
|
109 | ));
|
110 | place.push(tryCatchContinuation);
|
111 |
|
112 | handlerPlace.push(cont);
|
113 | if (this.block.async) {
|
114 |
|
115 | judgeIfException.alternate = cont;
|
116 | } else {
|
117 |
|
118 | handler.body.body.push(new ReturnStatement());
|
119 |
|
120 | catchFunction.body.body.push(cont);
|
121 | }
|
122 | var continuationPlace = continuationFunction.body.body;
|
123 | } else {
|
124 |
|
125 | place.push(tryCatch);
|
126 | var continuationPlace = handlerFunction.body.body;
|
127 | }
|
128 | }
|
129 |
|
130 |
|
131 | if (this.finalizer !== null) {
|
132 | for (var i = 0; i < this.finalizer.body.length; i++) {
|
133 | continuationPlace.push(this.finalizer.body[i]);
|
134 | }
|
135 | }
|
136 |
|
137 | return continuationPlace;
|
138 | };
|