This repository has been archived by the owner on Jan 13, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 66
/
es6-for-of-visitors.js
123 lines (104 loc) · 2.93 KB
/
es6-for-of-visitors.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/**
* Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
/*global exports:true*/
/**
* Implements ES6 for-of loop, making optimization
* for arrays. If an object is not an array, instantiates
* an iterator for this object, assuming the runtime
* support for the iterator is implemented.
*
* ES6:
*
* for (var v of <expr>) <body>
*
* Compiled ES3:
*
* for (var v,
* _iter = <expr>,
* _isArray = Array.isArray(_iter),
* _k = 0,
* _iter = _isArray ? _iter : _iter[Symbol.iterator]();;
* ) {
*
* if (_isArray) {
* if (_k >= _iter.length) break;
* v = _iter[_k++];
* } else {
* _k = _iter.next();
* if (_k.done) break;
* v = _k.value;
* }
*
* <body>
* }
*/
var Syntax = require('esprima-fb').Syntax;
var utils = require('../src/utils');
function process(traverse, node, path, state) {
utils.move(node.range[0], state);
traverse(node, path, state);
utils.catchup(node.range[1], state);
}
function visitForOfStatement(traverse, node, path, state) {
var iter = utils.injectTempVar(state);
var isArray = utils.injectTempVar(state);
var k = utils.injectTempVar(state);
var variable;
if (node.left.type === Syntax.VariableDeclaration) {
variable = node.left.declarations[0].id.name;
utils.append('var ' + variable + ';', state);
} else {
variable = node.left.name;
}
utils.append('for(', state);
utils.append(iter + '=', state);
process(traverse, node.right, path, state);
// Setup iterator with optimization for arrays.
utils.append(
',' + isArray + '=Array.isArray(' + iter + '),' +
k + '=0,' +
iter + '=' + isArray + '?' + iter + ':' +
iter + '[/*global Symbol*/typeof Symbol=="function"' +
'?Symbol.iterator:"@@iterator"]();;',
state
);
// Jump to the body creating block if needed.
if (node.body.type === Syntax.BlockStatement) {
utils.catchup(node.body.range[0] + 1, state);
} else {
utils.catchup(node.body.range[0], state);
utils.append('{', state);
}
// Arrays case.
utils.append(
'if(' + isArray + '){' +
'if(' + k + '>=' + iter + '.length) break;',
state
);
utils.append(variable + '=' + iter + '[' + k + '++];', state);
// Iterators case.
utils.append(
'}else{' + k + '=' + iter + '.next();' +
'if(' + k + '.done) break;',
state
);
utils.append(variable + '=' + k + '.value;}', state);
traverse(node.body, path, state);
utils.catchup(node.body.range[1], state);
if (node.body.type !== Syntax.BlockStatement) {
utils.append('}', state);
}
return false;
}
visitForOfStatement.test = function(node, path, state) {
return node.type === Syntax.ForOfStatement;
};
exports.visitorList = [
visitForOfStatement,
];