Codebase list node-ast-types / 6e44daf
New upstream version 0.10.1 Julien Puydt 6 years ago
9 changed file(s) with 2999 addition(s) and 2999 deletion(s). Raw diff Collapse all Expand all
0 module.exports = function (fork) {
1 fork.use(require("./es7"));
2
3 var types = fork.use(require("../lib/types"));
4 var defaults = fork.use(require("../lib/shared")).defaults;
5 var def = types.Type.def;
6 var or = types.Type.or;
7
8 def("Noop")
9 .bases("Node")
10 .build();
11
12 def("DoExpression")
13 .bases("Expression")
14 .build("body")
15 .field("body", [def("Statement")]);
16
17 def("Super")
18 .bases("Expression")
19 .build();
20
21 def("BindExpression")
22 .bases("Expression")
23 .build("object", "callee")
24 .field("object", or(def("Expression"), null))
25 .field("callee", def("Expression"));
26
27 def("Decorator")
28 .bases("Node")
29 .build("expression")
30 .field("expression", def("Expression"));
31
32 def("Property")
33 .field("decorators",
34 or([def("Decorator")], null),
35 defaults["null"]);
36
37 def("MethodDefinition")
38 .field("decorators",
39 or([def("Decorator")], null),
40 defaults["null"]);
41
42 def("MetaProperty")
43 .bases("Expression")
44 .build("meta", "property")
45 .field("meta", def("Identifier"))
46 .field("property", def("Identifier"));
47
48 def("ParenthesizedExpression")
49 .bases("Expression")
50 .build("expression")
51 .field("expression", def("Expression"));
52
53 def("ImportSpecifier")
54 .bases("ModuleSpecifier")
55 .build("imported", "local")
56 .field("imported", def("Identifier"));
57
58 def("ImportDefaultSpecifier")
59 .bases("ModuleSpecifier")
60 .build("local");
61
62 def("ImportNamespaceSpecifier")
63 .bases("ModuleSpecifier")
64 .build("local");
65
66 def("ExportDefaultDeclaration")
67 .bases("Declaration")
68 .build("declaration")
69 .field("declaration", or(def("Declaration"), def("Expression")));
70
71 def("ExportNamedDeclaration")
72 .bases("Declaration")
73 .build("declaration", "specifiers", "source")
74 .field("declaration", or(def("Declaration"), null))
75 .field("specifiers", [def("ExportSpecifier")], defaults.emptyArray)
76 .field("source", or(def("Literal"), null), defaults["null"]);
77
78 def("ExportSpecifier")
79 .bases("ModuleSpecifier")
80 .build("local", "exported")
81 .field("exported", def("Identifier"));
82
83 def("ExportNamespaceSpecifier")
84 .bases("Specifier")
85 .build("exported")
86 .field("exported", def("Identifier"));
87
88 def("ExportDefaultSpecifier")
89 .bases("Specifier")
90 .build("exported")
91 .field("exported", def("Identifier"));
92
93 def("ExportAllDeclaration")
94 .bases("Declaration")
95 .build("exported", "source")
96 .field("exported", or(def("Identifier"), null))
97 .field("source", def("Literal"));
98
99 def("CommentBlock")
100 .bases("Comment")
101 .build("value", /*optional:*/ "leading", "trailing");
102
103 def("CommentLine")
104 .bases("Comment")
105 .build("value", /*optional:*/ "leading", "trailing");
106
107 def("Directive")
108 .bases("Node")
109 .build("value")
110 .field("value", def("DirectiveLiteral"));
111
112 def("DirectiveLiteral")
113 .bases("Node", "Expression")
114 .build("value")
115 .field("value", String, defaults["use strict"]);
116
117 def("BlockStatement")
118 .bases("Statement")
119 .build("body")
120 .field("body", [def("Statement")])
121 .field("directives", [def("Directive")], defaults.emptyArray);
122
123 def("Program")
124 .bases("Node")
125 .build("body")
126 .field("body", [def("Statement")])
127 .field("directives", [def("Directive")], defaults.emptyArray);
128
129 // Split Literal
130 def("StringLiteral")
131 .bases("Literal")
132 .build("value")
133 .field("value", String);
134
135 def("NumericLiteral")
136 .bases("Literal")
137 .build("value")
138 .field("value", Number);
139
140 def("BigIntLiteral")
141 .bases("Literal")
142 .build("value")
143 // Only String really seems appropriate here, since BigInt values
144 // often exceed the limits of JS numbers.
145 .field("value", or(String, Number))
146 .field("extra", {
147 rawValue: String,
148 raw: String
149 }, function getDefault() {
150 return {
151 rawValue: String(this.value),
152 raw: this.value + "n"
153 };
154 });
155
156 def("NullLiteral")
157 .bases("Literal")
158 .build()
159 .field("value", null, defaults["null"]);
160
161 def("BooleanLiteral")
162 .bases("Literal")
163 .build("value")
164 .field("value", Boolean);
165
166 def("RegExpLiteral")
167 .bases("Literal")
168 .build("pattern", "flags")
169 .field("pattern", String)
170 .field("flags", String)
171 .field("value", RegExp, function () {
172 return new RegExp(this.pattern, this.flags);
173 });
174
175 var ObjectExpressionProperty = or(
176 def("Property"),
177 def("ObjectMethod"),
178 def("ObjectProperty"),
179 def("SpreadProperty")
180 );
181
182 // Split Property -> ObjectProperty and ObjectMethod
183 def("ObjectExpression")
184 .bases("Expression")
185 .build("properties")
186 .field("properties", [ObjectExpressionProperty]);
187
188 // ObjectMethod hoist .value properties to own properties
189 def("ObjectMethod")
190 .bases("Node", "Function")
191 .build("kind", "key", "params", "body", "computed")
192 .field("kind", or("method", "get", "set"))
193 .field("key", or(def("Literal"), def("Identifier"), def("Expression")))
194 .field("params", [def("Pattern")])
195 .field("body", def("BlockStatement"))
196 .field("computed", Boolean, defaults["false"])
197 .field("generator", Boolean, defaults["false"])
198 .field("async", Boolean, defaults["false"])
199 .field("decorators",
200 or([def("Decorator")], null),
201 defaults["null"]);
202
203 def("ObjectProperty")
204 .bases("Node")
205 .build("key", "value")
206 .field("key", or(def("Literal"), def("Identifier"), def("Expression")))
207 .field("value", or(def("Expression"), def("Pattern")))
208 .field("computed", Boolean, defaults["false"]);
209
210 var ClassBodyElement = or(
211 def("MethodDefinition"),
212 def("VariableDeclarator"),
213 def("ClassPropertyDefinition"),
214 def("ClassProperty"),
215 def("ClassMethod")
216 );
217
218 // MethodDefinition -> ClassMethod
219 def("ClassBody")
220 .bases("Declaration")
221 .build("body")
222 .field("body", [ClassBodyElement]);
223
224 def("ClassMethod")
225 .bases("Declaration", "Function")
226 .build("kind", "key", "params", "body", "computed", "static")
227 .field("kind", or("get", "set", "method", "constructor"))
228 .field("key", or(def("Literal"), def("Identifier"), def("Expression")))
229 .field("params", [def("Pattern")])
230 .field("body", def("BlockStatement"))
231 .field("computed", Boolean, defaults["false"])
232 .field("static", Boolean, defaults["false"])
233 .field("generator", Boolean, defaults["false"])
234 .field("async", Boolean, defaults["false"])
235 .field("decorators",
236 or([def("Decorator")], null),
237 defaults["null"]);
238
239 var ObjectPatternProperty = or(
240 def("Property"),
241 def("PropertyPattern"),
242 def("SpreadPropertyPattern"),
243 def("SpreadProperty"), // Used by Esprima
244 def("ObjectProperty"), // Babel 6
245 def("RestProperty") // Babel 6
246 );
247
248 // Split into RestProperty and SpreadProperty
249 def("ObjectPattern")
250 .bases("Pattern")
251 .build("properties")
252 .field("properties", [ObjectPatternProperty])
253 .field("decorators",
254 or([def("Decorator")], null),
255 defaults["null"]);
256
257 def("SpreadProperty")
258 .bases("Node")
259 .build("argument")
260 .field("argument", def("Expression"));
261
262 def("RestProperty")
263 .bases("Node")
264 .build("argument")
265 .field("argument", def("Expression"));
266
267 def("ForAwaitStatement")
268 .bases("Statement")
269 .build("left", "right", "body")
270 .field("left", or(
271 def("VariableDeclaration"),
272 def("Expression")))
273 .field("right", def("Expression"))
274 .field("body", def("Statement"));
275
276 // The callee node of a dynamic import(...) expression.
277 def("Import")
278 .bases("Expression")
279 .build();
280 };
00 module.exports = function (fork) {
1 fork.use(require("./es7"));
2
3 var types = fork.use(require("../lib/types"));
4 var defaults = fork.use(require("../lib/shared")).defaults;
5 var def = types.Type.def;
6 var or = types.Type.or;
7
8 def("Noop")
9 .bases("Node")
10 .build();
11
12 def("DoExpression")
13 .bases("Expression")
14 .build("body")
15 .field("body", [def("Statement")]);
16
17 def("Super")
18 .bases("Expression")
19 .build();
20
21 def("BindExpression")
22 .bases("Expression")
23 .build("object", "callee")
24 .field("object", or(def("Expression"), null))
25 .field("callee", def("Expression"));
26
27 def("Decorator")
28 .bases("Node")
29 .build("expression")
30 .field("expression", def("Expression"));
31
32 def("Property")
33 .field("decorators",
34 or([def("Decorator")], null),
35 defaults["null"]);
36
37 def("MethodDefinition")
38 .field("decorators",
39 or([def("Decorator")], null),
40 defaults["null"]);
41
42 def("MetaProperty")
43 .bases("Expression")
44 .build("meta", "property")
45 .field("meta", def("Identifier"))
46 .field("property", def("Identifier"));
47
48 def("ParenthesizedExpression")
49 .bases("Expression")
50 .build("expression")
51 .field("expression", def("Expression"));
52
53 def("ImportSpecifier")
54 .bases("ModuleSpecifier")
55 .build("imported", "local")
56 .field("imported", def("Identifier"));
57
58 def("ImportDefaultSpecifier")
59 .bases("ModuleSpecifier")
60 .build("local");
61
62 def("ImportNamespaceSpecifier")
63 .bases("ModuleSpecifier")
64 .build("local");
65
66 def("ExportDefaultDeclaration")
67 .bases("Declaration")
68 .build("declaration")
69 .field("declaration", or(def("Declaration"), def("Expression")));
70
71 def("ExportNamedDeclaration")
72 .bases("Declaration")
73 .build("declaration", "specifiers", "source")
74 .field("declaration", or(def("Declaration"), null))
75 .field("specifiers", [def("ExportSpecifier")], defaults.emptyArray)
76 .field("source", or(def("Literal"), null), defaults["null"]);
77
78 def("ExportSpecifier")
79 .bases("ModuleSpecifier")
80 .build("local", "exported")
81 .field("exported", def("Identifier"));
82
83 def("ExportNamespaceSpecifier")
84 .bases("Specifier")
85 .build("exported")
86 .field("exported", def("Identifier"));
87
88 def("ExportDefaultSpecifier")
89 .bases("Specifier")
90 .build("exported")
91 .field("exported", def("Identifier"));
92
93 def("ExportAllDeclaration")
94 .bases("Declaration")
95 .build("exported", "source")
96 .field("exported", or(def("Identifier"), null))
97 .field("source", def("Literal"));
98
99 def("CommentBlock")
100 .bases("Comment")
101 .build("value", /*optional:*/ "leading", "trailing");
102
103 def("CommentLine")
104 .bases("Comment")
105 .build("value", /*optional:*/ "leading", "trailing");
106 };
1 fork.use(require("./babel-core"));
2 fork.use(require("./flow"));
3 };
+0
-168
def/babel6-core.js less more
0 module.exports = function (fork) {
1 fork.use(require("./babel"));
2
3 // var types = fork.types;
4 var types = fork.use(require("../lib/types"));
5 // var defaults = fork.shared.defaults;
6 var defaults = fork.use(require("../lib/shared")).defaults;
7 var def = types.Type.def;
8 var or = types.Type.or;
9
10 def("Directive")
11 .bases("Node")
12 .build("value")
13 .field("value", def("DirectiveLiteral"));
14
15 def("DirectiveLiteral")
16 .bases("Node", "Expression")
17 .build("value")
18 .field("value", String, defaults["use strict"]);
19
20 def("BlockStatement")
21 .bases("Statement")
22 .build("body")
23 .field("body", [def("Statement")])
24 .field("directives", [def("Directive")], defaults.emptyArray);
25
26 def("Program")
27 .bases("Node")
28 .build("body")
29 .field("body", [def("Statement")])
30 .field("directives", [def("Directive")], defaults.emptyArray);
31
32 // Split Literal
33 def("StringLiteral")
34 .bases("Literal")
35 .build("value")
36 .field("value", String);
37
38 def("NumericLiteral")
39 .bases("Literal")
40 .build("value")
41 .field("value", Number);
42
43 def("NullLiteral")
44 .bases("Literal")
45 .build()
46 .field("value", null, defaults["null"]);
47
48 def("BooleanLiteral")
49 .bases("Literal")
50 .build("value")
51 .field("value", Boolean);
52
53 def("RegExpLiteral")
54 .bases("Literal")
55 .build("pattern", "flags")
56 .field("pattern", String)
57 .field("flags", String)
58 .field("value", RegExp, function () {
59 return new RegExp(this.pattern, this.flags);
60 });
61
62 var ObjectExpressionProperty = or(
63 def("Property"),
64 def("ObjectMethod"),
65 def("ObjectProperty"),
66 def("SpreadProperty")
67 );
68
69 // Split Property -> ObjectProperty and ObjectMethod
70 def("ObjectExpression")
71 .bases("Expression")
72 .build("properties")
73 .field("properties", [ObjectExpressionProperty]);
74
75 // ObjectMethod hoist .value properties to own properties
76 def("ObjectMethod")
77 .bases("Node", "Function")
78 .build("kind", "key", "params", "body", "computed")
79 .field("kind", or("method", "get", "set"))
80 .field("key", or(def("Literal"), def("Identifier"), def("Expression")))
81 .field("params", [def("Pattern")])
82 .field("body", def("BlockStatement"))
83 .field("computed", Boolean, defaults["false"])
84 .field("generator", Boolean, defaults["false"])
85 .field("async", Boolean, defaults["false"])
86 .field("decorators",
87 or([def("Decorator")], null),
88 defaults["null"]);
89
90 def("ObjectProperty")
91 .bases("Node")
92 .build("key", "value")
93 .field("key", or(def("Literal"), def("Identifier"), def("Expression")))
94 .field("value", or(def("Expression"), def("Pattern")))
95 .field("computed", Boolean, defaults["false"]);
96
97 var ClassBodyElement = or(
98 def("MethodDefinition"),
99 def("VariableDeclarator"),
100 def("ClassPropertyDefinition"),
101 def("ClassProperty"),
102 def("ClassMethod")
103 );
104
105 // MethodDefinition -> ClassMethod
106 def("ClassBody")
107 .bases("Declaration")
108 .build("body")
109 .field("body", [ClassBodyElement]);
110
111 def("ClassMethod")
112 .bases("Declaration", "Function")
113 .build("kind", "key", "params", "body", "computed", "static")
114 .field("kind", or("get", "set", "method", "constructor"))
115 .field("key", or(def("Literal"), def("Identifier"), def("Expression")))
116 .field("params", [def("Pattern")])
117 .field("body", def("BlockStatement"))
118 .field("computed", Boolean, defaults["false"])
119 .field("static", Boolean, defaults["false"])
120 .field("generator", Boolean, defaults["false"])
121 .field("async", Boolean, defaults["false"])
122 .field("decorators",
123 or([def("Decorator")], null),
124 defaults["null"]);
125
126 var ObjectPatternProperty = or(
127 def("Property"),
128 def("PropertyPattern"),
129 def("SpreadPropertyPattern"),
130 def("SpreadProperty"), // Used by Esprima
131 def("ObjectProperty"), // Babel 6
132 def("RestProperty") // Babel 6
133 );
134
135 // Split into RestProperty and SpreadProperty
136 def("ObjectPattern")
137 .bases("Pattern")
138 .build("properties")
139 .field("properties", [ObjectPatternProperty])
140 .field("decorators",
141 or([def("Decorator")], null),
142 defaults["null"]);
143
144 def("SpreadProperty")
145 .bases("Node")
146 .build("argument")
147 .field("argument", def("Expression"));
148
149 def("RestProperty")
150 .bases("Node")
151 .build("argument")
152 .field("argument", def("Expression"));
153
154 def("ForAwaitStatement")
155 .bases("Statement")
156 .build("left", "right", "body")
157 .field("left", or(
158 def("VariableDeclaration"),
159 def("Expression")))
160 .field("right", def("Expression"))
161 .field("body", def("Statement"));
162
163 // The callee node of a dynamic import(...) expression.
164 def("Import")
165 .bases("Expression")
166 .build();
167 };
+0
-4
def/babel6.js less more
0 module.exports = function (fork) {
1 fork.use(require("./babel6-core"));
2 fork.use(require("./flow"));
3 };
00 module.exports = function (fork) {
1 fork.use(require("./es7"));
2
3 var types = fork.use(require("../lib/types"));
4 var def = types.Type.def;
5 var or = types.Type.or;
6 var defaults = fork.use(require("../lib/shared")).defaults;
7
8 // Type Annotations
9 def("Type").bases("Node");
10
11 def("AnyTypeAnnotation")
12 .bases("Type")
13 .build();
14
15 def("EmptyTypeAnnotation")
16 .bases("Type")
17 .build();
18
19 def("MixedTypeAnnotation")
20 .bases("Type")
21 .build();
22
23 def("VoidTypeAnnotation")
24 .bases("Type")
25 .build();
26
27 def("NumberTypeAnnotation")
28 .bases("Type")
29 .build();
30
31 def("NumberLiteralTypeAnnotation")
32 .bases("Type")
33 .build("value", "raw")
34 .field("value", Number)
35 .field("raw", String);
36
37 // Babylon 6 differs in AST from Flow
38 // same as NumberLiteralTypeAnnotation
39 def("NumericLiteralTypeAnnotation")
40 .bases("Type")
41 .build("value", "raw")
42 .field("value", Number)
43 .field("raw", String);
44
45 def("StringTypeAnnotation")
46 .bases("Type")
47 .build();
48
49 def("StringLiteralTypeAnnotation")
50 .bases("Type")
51 .build("value", "raw")
52 .field("value", String)
53 .field("raw", String);
54
55 def("BooleanTypeAnnotation")
56 .bases("Type")
57 .build();
58
59 def("BooleanLiteralTypeAnnotation")
60 .bases("Type")
61 .build("value", "raw")
62 .field("value", Boolean)
63 .field("raw", String);
64
65 def("TypeAnnotation")
66 .bases("Node")
67 .build("typeAnnotation")
68 .field("typeAnnotation", def("Type"));
69
70 def("NullableTypeAnnotation")
71 .bases("Type")
72 .build("typeAnnotation")
73 .field("typeAnnotation", def("Type"));
74
75 def("NullLiteralTypeAnnotation")
76 .bases("Type")
77 .build();
78
79 def("NullTypeAnnotation")
80 .bases("Type")
81 .build();
82
83 def("ThisTypeAnnotation")
84 .bases("Type")
85 .build();
86
87 def("ExistsTypeAnnotation")
88 .bases("Type")
89 .build();
90
91 def("ExistentialTypeParam")
92 .bases("Type")
93 .build();
94
95 def("FunctionTypeAnnotation")
96 .bases("Type")
97 .build("params", "returnType", "rest", "typeParameters")
98 .field("params", [def("FunctionTypeParam")])
99 .field("returnType", def("Type"))
100 .field("rest", or(def("FunctionTypeParam"), null))
101 .field("typeParameters", or(def("TypeParameterDeclaration"), null));
102
103 def("FunctionTypeParam")
104 .bases("Node")
105 .build("name", "typeAnnotation", "optional")
106 .field("name", def("Identifier"))
107 .field("typeAnnotation", def("Type"))
108 .field("optional", Boolean);
109
110 def("ArrayTypeAnnotation")
111 .bases("Type")
112 .build("elementType")
113 .field("elementType", def("Type"));
114
115 def("ObjectTypeAnnotation")
116 .bases("Type")
117 .build("properties", "indexers", "callProperties")
118 .field("properties", [or(def("ObjectTypeProperty"), def("ObjectTypeSpreadProperty"))])
119 .field("indexers", [def("ObjectTypeIndexer")], defaults.emptyArray)
120 .field("callProperties",
121 [def("ObjectTypeCallProperty")],
122 defaults.emptyArray)
123 .field("exact", Boolean, defaults["false"]);
124
125 def("ObjectTypeProperty")
126 .bases("Node")
127 .build("key", "value", "optional")
128 .field("key", or(def("Literal"), def("Identifier")))
129 .field("value", def("Type"))
130 .field("optional", Boolean)
131 .field("variance",
132 or("plus", "minus", null),
133 defaults["null"]);
134
135 def("ObjectTypeIndexer")
136 .bases("Node")
137 .build("id", "key", "value")
138 .field("id", def("Identifier"))
139 .field("key", def("Type"))
140 .field("value", def("Type"))
141 .field("variance",
142 or("plus", "minus", null),
143 defaults["null"]);
144
145 def("ObjectTypeCallProperty")
146 .bases("Node")
147 .build("value")
148 .field("value", def("FunctionTypeAnnotation"))
149 .field("static", Boolean, defaults["false"]);
150
151 def("QualifiedTypeIdentifier")
152 .bases("Node")
153 .build("qualification", "id")
154 .field("qualification",
155 or(def("Identifier"),
156 def("QualifiedTypeIdentifier")))
157 .field("id", def("Identifier"));
158
159 def("GenericTypeAnnotation")
160 .bases("Type")
161 .build("id", "typeParameters")
162 .field("id", or(def("Identifier"), def("QualifiedTypeIdentifier")))
163 .field("typeParameters", or(def("TypeParameterInstantiation"), null));
164
165 def("MemberTypeAnnotation")
166 .bases("Type")
167 .build("object", "property")
168 .field("object", def("Identifier"))
169 .field("property",
170 or(def("MemberTypeAnnotation"),
171 def("GenericTypeAnnotation")));
172
173 def("UnionTypeAnnotation")
174 .bases("Type")
175 .build("types")
176 .field("types", [def("Type")]);
177
178 def("IntersectionTypeAnnotation")
179 .bases("Type")
180 .build("types")
181 .field("types", [def("Type")]);
182
183 def("TypeofTypeAnnotation")
184 .bases("Type")
185 .build("argument")
186 .field("argument", def("Type"));
187
188 def("ObjectTypeSpreadProperty")
189 .bases("Node")
190 .build("argument")
191 .field("argument", def("Type"));
192
193 def("Identifier")
194 .field("typeAnnotation", or(def("TypeAnnotation"), null), defaults["null"]);
195
196 def("ObjectPattern")
197 .field("typeAnnotation", or(def("TypeAnnotation"), null), defaults["null"]);
198
199 def("TypeParameterDeclaration")
200 .bases("Node")
201 .build("params")
202 .field("params", [def("TypeParameter")]);
203
204 def("TypeParameterInstantiation")
205 .bases("Node")
206 .build("params")
207 .field("params", [def("Type")]);
208
209 def("TypeParameter")
210 .bases("Type")
211 .build("name", "variance", "bound")
212 .field("name", String)
213 .field("variance",
214 or("plus", "minus", null),
215 defaults["null"])
216 .field("bound",
217 or(def("TypeAnnotation"), null),
218 defaults["null"]);
219
220 def("Function")
221 .field("returnType",
222 or(def("TypeAnnotation"), null),
223 defaults["null"])
224 .field("typeParameters",
225 or(def("TypeParameterDeclaration"), null),
226 defaults["null"]);
227
228 def("ClassProperty")
229 .build("key", "value", "typeAnnotation", "static")
230 .field("value", or(def("Expression"), null))
231 .field("typeAnnotation", or(def("TypeAnnotation"), null))
232 .field("static", Boolean, defaults["false"])
233 .field("variance",
234 or("plus", "minus", null),
235 defaults["null"]);
236
237 def("ClassImplements")
238 .field("typeParameters",
239 or(def("TypeParameterInstantiation"), null),
240 defaults["null"]);
241
242 def("InterfaceDeclaration")
243 .bases("Declaration")
244 .build("id", "body", "extends")
245 .field("id", def("Identifier"))
246 .field("typeParameters",
247 or(def("TypeParameterDeclaration"), null),
248 defaults["null"])
249 .field("body", def("ObjectTypeAnnotation"))
250 .field("extends", [def("InterfaceExtends")]);
251
252 def("DeclareInterface")
253 .bases("InterfaceDeclaration")
254 .build("id", "body", "extends");
255
256 def("InterfaceExtends")
257 .bases("Node")
258 .build("id")
259 .field("id", def("Identifier"))
260 .field("typeParameters", or(def("TypeParameterInstantiation"), null));
261
262 def("TypeAlias")
263 .bases("Declaration")
264 .build("id", "typeParameters", "right")
265 .field("id", def("Identifier"))
266 .field("typeParameters", or(def("TypeParameterDeclaration"), null))
267 .field("right", def("Type"));
268
269 def("OpaqueType")
270 .bases("Declaration")
271 .build("id", "typeParameters", "impltype", "supertype")
272 .field("id", def("Identifier"))
273 .field("typeParameters", or(def("TypeParameterDeclaration"), null))
274 .field("implType", def("Type"))
275 .field("superType", def("Type"));
276
277 def("DeclareTypeAlias")
278 .bases("TypeAlias")
279 .build("id", "typeParameters", "right");
280
281 def("DeclareOpaqueType")
282 .bases("TypeAlias")
283 .build("id", "typeParameters", "supertype");
284
285 def("TypeCastExpression")
286 .bases("Expression")
287 .build("expression", "typeAnnotation")
288 .field("expression", def("Expression"))
289 .field("typeAnnotation", def("TypeAnnotation"));
290
291 def("TupleTypeAnnotation")
292 .bases("Type")
293 .build("types")
294 .field("types", [def("Type")]);
295
296 def("DeclareVariable")
297 .bases("Statement")
298 .build("id")
299 .field("id", def("Identifier"));
300
301 def("DeclareFunction")
302 .bases("Statement")
303 .build("id")
304 .field("id", def("Identifier"));
305
306 def("DeclareClass")
307 .bases("InterfaceDeclaration")
308 .build("id");
309
310 def("DeclareModule")
311 .bases("Statement")
312 .build("id", "body")
313 .field("id", or(def("Identifier"), def("Literal")))
314 .field("body", def("BlockStatement"));
315
316 def("DeclareModuleExports")
317 .bases("Statement")
318 .build("typeAnnotation")
319 .field("typeAnnotation", def("Type"));
320
321 def("DeclareExportDeclaration")
322 .bases("Declaration")
323 .build("default", "declaration", "specifiers", "source")
324 .field("default", Boolean)
325 .field("declaration", or(
326 def("DeclareVariable"),
327 def("DeclareFunction"),
328 def("DeclareClass"),
329 def("Type"), // Implies default.
330 null
331 ))
332 .field("specifiers", [or(
333 def("ExportSpecifier"),
334 def("ExportBatchSpecifier")
335 )], defaults.emptyArray)
336 .field("source", or(
337 def("Literal"),
338 null
339 ), defaults["null"]);
340
341 def("DeclareExportAllDeclaration")
342 .bases("Declaration")
343 .build("source")
344 .field("source", or(
345 def("Literal"),
346 null
347 ), defaults["null"]);
1 fork.use(require("./es7"));
2
3 var types = fork.use(require("../lib/types"));
4 var def = types.Type.def;
5 var or = types.Type.or;
6 var defaults = fork.use(require("../lib/shared")).defaults;
7
8 // Type Annotations
9 def("Type").bases("Node");
10
11 def("AnyTypeAnnotation")
12 .bases("Type")
13 .build();
14
15 def("EmptyTypeAnnotation")
16 .bases("Type")
17 .build();
18
19 def("MixedTypeAnnotation")
20 .bases("Type")
21 .build();
22
23 def("VoidTypeAnnotation")
24 .bases("Type")
25 .build();
26
27 def("NumberTypeAnnotation")
28 .bases("Type")
29 .build();
30
31 def("NumberLiteralTypeAnnotation")
32 .bases("Type")
33 .build("value", "raw")
34 .field("value", Number)
35 .field("raw", String);
36
37 // Babylon 6 differs in AST from Flow
38 // same as NumberLiteralTypeAnnotation
39 def("NumericLiteralTypeAnnotation")
40 .bases("Type")
41 .build("value", "raw")
42 .field("value", Number)
43 .field("raw", String);
44
45 def("StringTypeAnnotation")
46 .bases("Type")
47 .build();
48
49 def("StringLiteralTypeAnnotation")
50 .bases("Type")
51 .build("value", "raw")
52 .field("value", String)
53 .field("raw", String);
54
55 def("BooleanTypeAnnotation")
56 .bases("Type")
57 .build();
58
59 def("BooleanLiteralTypeAnnotation")
60 .bases("Type")
61 .build("value", "raw")
62 .field("value", Boolean)
63 .field("raw", String);
64
65 def("TypeAnnotation")
66 .bases("Node")
67 .build("typeAnnotation")
68 .field("typeAnnotation", def("Type"));
69
70 def("NullableTypeAnnotation")
71 .bases("Type")
72 .build("typeAnnotation")
73 .field("typeAnnotation", def("Type"));
74
75 def("NullLiteralTypeAnnotation")
76 .bases("Type")
77 .build();
78
79 def("NullTypeAnnotation")
80 .bases("Type")
81 .build();
82
83 def("ThisTypeAnnotation")
84 .bases("Type")
85 .build();
86
87 def("ExistsTypeAnnotation")
88 .bases("Type")
89 .build();
90
91 def("ExistentialTypeParam")
92 .bases("Type")
93 .build();
94
95 def("FunctionTypeAnnotation")
96 .bases("Type")
97 .build("params", "returnType", "rest", "typeParameters")
98 .field("params", [def("FunctionTypeParam")])
99 .field("returnType", def("Type"))
100 .field("rest", or(def("FunctionTypeParam"), null))
101 .field("typeParameters", or(def("TypeParameterDeclaration"), null));
102
103 def("FunctionTypeParam")
104 .bases("Node")
105 .build("name", "typeAnnotation", "optional")
106 .field("name", def("Identifier"))
107 .field("typeAnnotation", def("Type"))
108 .field("optional", Boolean);
109
110 def("ArrayTypeAnnotation")
111 .bases("Type")
112 .build("elementType")
113 .field("elementType", def("Type"));
114
115 def("ObjectTypeAnnotation")
116 .bases("Type")
117 .build("properties", "indexers", "callProperties")
118 .field("properties", [
119 or(def("ObjectTypeProperty"),
120 def("ObjectTypeSpreadProperty"))
121 ])
122 .field("indexers", [def("ObjectTypeIndexer")], defaults.emptyArray)
123 .field("callProperties",
124 [def("ObjectTypeCallProperty")],
125 defaults.emptyArray)
126 .field("exact", Boolean, defaults["false"]);
127
128 def("Variance")
129 .bases("Node")
130 .build("kind")
131 .field("kind", or("plus", "minus"));
132
133 var LegacyVariance = or(
134 def("Variance"),
135 "plus",
136 "minus",
137 null
138 );
139
140 def("ObjectTypeProperty")
141 .bases("Node")
142 .build("key", "value", "optional")
143 .field("key", or(def("Literal"), def("Identifier")))
144 .field("value", def("Type"))
145 .field("optional", Boolean)
146 .field("variance", LegacyVariance, defaults["null"]);
147
148 def("ObjectTypeIndexer")
149 .bases("Node")
150 .build("id", "key", "value")
151 .field("id", def("Identifier"))
152 .field("key", def("Type"))
153 .field("value", def("Type"))
154 .field("variance", LegacyVariance, defaults["null"]);
155
156 def("ObjectTypeCallProperty")
157 .bases("Node")
158 .build("value")
159 .field("value", def("FunctionTypeAnnotation"))
160 .field("static", Boolean, defaults["false"]);
161
162 def("QualifiedTypeIdentifier")
163 .bases("Node")
164 .build("qualification", "id")
165 .field("qualification",
166 or(def("Identifier"),
167 def("QualifiedTypeIdentifier")))
168 .field("id", def("Identifier"));
169
170 def("GenericTypeAnnotation")
171 .bases("Type")
172 .build("id", "typeParameters")
173 .field("id", or(def("Identifier"), def("QualifiedTypeIdentifier")))
174 .field("typeParameters", or(def("TypeParameterInstantiation"), null));
175
176 def("MemberTypeAnnotation")
177 .bases("Type")
178 .build("object", "property")
179 .field("object", def("Identifier"))
180 .field("property",
181 or(def("MemberTypeAnnotation"),
182 def("GenericTypeAnnotation")));
183
184 def("UnionTypeAnnotation")
185 .bases("Type")
186 .build("types")
187 .field("types", [def("Type")]);
188
189 def("IntersectionTypeAnnotation")
190 .bases("Type")
191 .build("types")
192 .field("types", [def("Type")]);
193
194 def("TypeofTypeAnnotation")
195 .bases("Type")
196 .build("argument")
197 .field("argument", def("Type"));
198
199 def("ObjectTypeSpreadProperty")
200 .bases("Node")
201 .build("argument")
202 .field("argument", def("Type"));
203
204 def("Identifier")
205 .field("typeAnnotation", or(def("TypeAnnotation"), null), defaults["null"]);
206
207 def("ObjectPattern")
208 .field("typeAnnotation", or(def("TypeAnnotation"), null), defaults["null"]);
209
210 def("TypeParameterDeclaration")
211 .bases("Node")
212 .build("params")
213 .field("params", [def("TypeParameter")]);
214
215 def("TypeParameterInstantiation")
216 .bases("Node")
217 .build("params")
218 .field("params", [def("Type")]);
219
220 def("TypeParameter")
221 .bases("Type")
222 .build("name", "variance", "bound")
223 .field("name", String)
224 .field("variance", LegacyVariance, defaults["null"])
225 .field("bound",
226 or(def("TypeAnnotation"), null),
227 defaults["null"]);
228
229 def("Function")
230 .field("returnType",
231 or(def("TypeAnnotation"), null),
232 defaults["null"])
233 .field("typeParameters",
234 or(def("TypeParameterDeclaration"), null),
235 defaults["null"]);
236
237 def("ClassProperty")
238 .build("key", "value", "typeAnnotation", "static")
239 .field("value", or(def("Expression"), null))
240 .field("typeAnnotation", or(def("TypeAnnotation"), null))
241 .field("static", Boolean, defaults["false"])
242 .field("variance", LegacyVariance, defaults["null"]);
243
244 def("ClassImplements")
245 .field("typeParameters",
246 or(def("TypeParameterInstantiation"), null),
247 defaults["null"]);
248
249 def("InterfaceDeclaration")
250 .bases("Declaration")
251 .build("id", "body", "extends")
252 .field("id", def("Identifier"))
253 .field("typeParameters",
254 or(def("TypeParameterDeclaration"), null),
255 defaults["null"])
256 .field("body", def("ObjectTypeAnnotation"))
257 .field("extends", [def("InterfaceExtends")]);
258
259 def("DeclareInterface")
260 .bases("InterfaceDeclaration")
261 .build("id", "body", "extends");
262
263 def("InterfaceExtends")
264 .bases("Node")
265 .build("id")
266 .field("id", def("Identifier"))
267 .field("typeParameters", or(def("TypeParameterInstantiation"), null));
268
269 def("TypeAlias")
270 .bases("Declaration")
271 .build("id", "typeParameters", "right")
272 .field("id", def("Identifier"))
273 .field("typeParameters", or(def("TypeParameterDeclaration"), null))
274 .field("right", def("Type"));
275
276 def("OpaqueType")
277 .bases("Declaration")
278 .build("id", "typeParameters", "impltype", "supertype")
279 .field("id", def("Identifier"))
280 .field("typeParameters", or(def("TypeParameterDeclaration"), null))
281 .field("implType", def("Type"))
282 .field("superType", def("Type"));
283
284 def("DeclareTypeAlias")
285 .bases("TypeAlias")
286 .build("id", "typeParameters", "right");
287
288 def("DeclareOpaqueType")
289 .bases("TypeAlias")
290 .build("id", "typeParameters", "supertype");
291
292 def("TypeCastExpression")
293 .bases("Expression")
294 .build("expression", "typeAnnotation")
295 .field("expression", def("Expression"))
296 .field("typeAnnotation", def("TypeAnnotation"));
297
298 def("TupleTypeAnnotation")
299 .bases("Type")
300 .build("types")
301 .field("types", [def("Type")]);
302
303 def("DeclareVariable")
304 .bases("Statement")
305 .build("id")
306 .field("id", def("Identifier"));
307
308 def("DeclareFunction")
309 .bases("Statement")
310 .build("id")
311 .field("id", def("Identifier"));
312
313 def("DeclareClass")
314 .bases("InterfaceDeclaration")
315 .build("id");
316
317 def("DeclareModule")
318 .bases("Statement")
319 .build("id", "body")
320 .field("id", or(def("Identifier"), def("Literal")))
321 .field("body", def("BlockStatement"));
322
323 def("DeclareModuleExports")
324 .bases("Statement")
325 .build("typeAnnotation")
326 .field("typeAnnotation", def("Type"));
327
328 def("DeclareExportDeclaration")
329 .bases("Declaration")
330 .build("default", "declaration", "specifiers", "source")
331 .field("default", Boolean)
332 .field("declaration", or(
333 def("DeclareVariable"),
334 def("DeclareFunction"),
335 def("DeclareClass"),
336 def("Type"), // Implies default.
337 null
338 ))
339 .field("specifiers", [or(
340 def("ExportSpecifier"),
341 def("ExportBatchSpecifier")
342 )], defaults.emptyArray)
343 .field("source", or(
344 def("Literal"),
345 null
346 ), defaults["null"]);
347
348 def("DeclareExportAllDeclaration")
349 .bases("Declaration")
350 .build("source")
351 .field("source", or(
352 def("Literal"),
353 null
354 ), defaults["null"]);
348355 };
00 module.exports = require('./fork')([
1 // This core module of AST types captures ES5 as it is parsed today by
2 // git://github.com/ariya/esprima.git#master.
3 require("./def/core"),
1 // This core module of AST types captures ES5 as it is parsed today by
2 // git://github.com/ariya/esprima.git#master.
3 require("./def/core"),
44
5 // Feel free to add to or remove from this list of extension modules to
6 // configure the precise type hierarchy that you need.
7 require("./def/es6"),
8 require("./def/es7"),
9 require("./def/mozilla"),
10 require("./def/e4x"),
11 require("./def/jsx"),
12 require("./def/flow"),
13 require("./def/esprima"),
14 require("./def/babel"),
15 require("./def/babel6")
5 // Feel free to add to or remove from this list of extension modules to
6 // configure the precise type hierarchy that you need.
7 require("./def/es6"),
8 require("./def/es7"),
9 require("./def/mozilla"),
10 require("./def/e4x"),
11 require("./def/jsx"),
12 require("./def/flow"),
13 require("./def/esprima"),
14 require("./def/babel")
1615 ]);
00 {
11 "name": "ast-types",
2 "version": "0.9.14",
2 "version": "0.10.1",
33 "lockfileVersion": 1,
44 "requires": true,
55 "dependencies": {
66 "acorn": {
7 "version": "5.1.2",
8 "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.1.2.tgz",
9 "integrity": "sha512-o96FZLJBPY1lvTuJylGA9Bk3t/GKPPJG8H0ydQQl01crzwJgspa4AEIq/pVTXigmK0PHVQhiAtn8WMBLL9D2WA==",
7 "version": "5.2.1",
8 "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.2.1.tgz",
9 "integrity": "sha512-jG0u7c4Ly+3QkkW18V+NRDN+4bWHdln30NL1ZL2AvFZZmQe/BfopYCtghCKKVBUSetZ4QKcyA0pY6/4Gw8Pv8w==",
1010 "dev": true
1111 },
1212 "acorn-jsx": {
4949 }
5050 },
5151 "babylon": {
52 "version": "6.18.0",
53 "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
54 "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==",
52 "version": "7.0.0-beta.31",
53 "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.31.tgz",
54 "integrity": "sha512-6lm2mV3S51yEnKmQQNnswoABL1U1H1KHoCCVwdwI3hvIv+W7ya4ki7Aw4o4KxtUHjNKkK5WpZb22rrMMOcJXJQ==",
5555 "dev": true
5656 },
5757 "balanced-match": {
7777 "dev": true
7878 },
7979 "commander": {
80 "version": "2.9.0",
81 "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz",
82 "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=",
83 "dev": true,
84 "requires": {
85 "graceful-readlink": "1.0.1"
86 }
80 "version": "2.11.0",
81 "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz",
82 "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==",
83 "dev": true
8784 },
8885 "concat-map": {
8986 "version": "0.0.1",
9895 "dev": true
9996 },
10097 "debug": {
101 "version": "2.6.8",
102 "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz",
103 "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=",
98 "version": "3.1.0",
99 "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
100 "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
104101 "dev": true,
105102 "requires": {
106103 "ms": "2.0.0"
107104 }
108105 },
109106 "diff": {
110 "version": "3.2.0",
111 "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz",
112 "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=",
107 "version": "3.3.1",
108 "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz",
109 "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==",
113110 "dev": true
114111 },
115112 "escape-string-regexp": {
119116 "dev": true
120117 },
121118 "espree": {
122 "version": "3.5.1",
123 "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.1.tgz",
124 "integrity": "sha1-DJiLirRttTEAoZVK5LqZXd0n2H4=",
125 "dev": true,
126 "requires": {
127 "acorn": "5.1.2",
119 "version": "3.5.2",
120 "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.2.tgz",
121 "integrity": "sha512-sadKeYwaR/aJ3stC2CdvgXu1T16TdYN+qwCpcWbMnGJ8s0zNWemzrvb2GbD4OhmJ/fwpJjudThAlLobGbWZbCQ==",
122 "dev": true,
123 "requires": {
124 "acorn": "5.2.1",
128125 "acorn-jsx": "3.0.1"
129126 }
130127 },
153150 "dev": true
154151 },
155152 "glob": {
156 "version": "7.1.1",
157 "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz",
158 "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=",
153 "version": "7.1.2",
154 "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
155 "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
159156 "dev": true,
160157 "requires": {
161158 "fs.realpath": "1.0.0",
166163 "path-is-absolute": "1.0.1"
167164 }
168165 },
169 "graceful-readlink": {
170 "version": "1.0.1",
171 "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
172 "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=",
173 "dev": true
174 },
175166 "growl": {
176 "version": "1.9.2",
177 "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz",
178 "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=",
167 "version": "1.10.3",
168 "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz",
169 "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==",
179170 "dev": true
180171 },
181172 "has-flag": {
182 "version": "1.0.0",
183 "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
184 "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
173 "version": "2.0.0",
174 "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
175 "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
185176 "dev": true
186177 },
187178 "he": {
206197 "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
207198 "dev": true
208199 },
209 "json3": {
210 "version": "3.3.2",
211 "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz",
212 "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=",
213 "dev": true
214 },
215200 "lodash": {
216201 "version": "4.17.4",
217202 "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
218203 "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=",
219204 "dev": true
220205 },
221 "lodash._baseassign": {
222 "version": "3.2.0",
223 "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz",
224 "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=",
225 "dev": true,
226 "requires": {
227 "lodash._basecopy": "3.0.1",
228 "lodash.keys": "3.1.2"
229 }
230 },
231 "lodash._basecopy": {
232 "version": "3.0.1",
233 "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz",
234 "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=",
235 "dev": true
236 },
237 "lodash._basecreate": {
238 "version": "3.0.3",
239 "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz",
240 "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=",
241 "dev": true
242 },
243 "lodash._getnative": {
244 "version": "3.9.1",
245 "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz",
246 "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=",
247 "dev": true
248 },
249 "lodash._isiterateecall": {
250 "version": "3.0.9",
251 "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz",
252 "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=",
253 "dev": true
254 },
255 "lodash.create": {
256 "version": "3.1.1",
257 "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz",
258 "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=",
259 "dev": true,
260 "requires": {
261 "lodash._baseassign": "3.2.0",
262 "lodash._basecreate": "3.0.3",
263 "lodash._isiterateecall": "3.0.9"
264 }
265 },
266 "lodash.isarguments": {
267 "version": "3.1.0",
268 "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
269 "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=",
270 "dev": true
271 },
272 "lodash.isarray": {
273 "version": "3.0.4",
274 "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz",
275 "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=",
276 "dev": true
277 },
278 "lodash.keys": {
279 "version": "3.1.2",
280 "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz",
281 "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=",
282 "dev": true,
283 "requires": {
284 "lodash._getnative": "3.9.1",
285 "lodash.isarguments": "3.1.0",
286 "lodash.isarray": "3.0.4"
287 }
288 },
289206 "minimatch": {
290207 "version": "3.0.4",
291208 "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
311228 }
312229 },
313230 "minizlib": {
314 "version": "1.0.3",
315 "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.0.3.tgz",
316 "integrity": "sha1-1cGr93vhVGGZUuJTM27Mq5sqMvU=",
231 "version": "1.0.4",
232 "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.0.4.tgz",
233 "integrity": "sha512-sN4U9tIJtBRwKbwgFh9qJfrPIQ/GGTRr1MGqkgOeMTLy8/lM0FcWU//FqlnZ3Vb7gJ+Mxh3FOg1EklibdajbaQ==",
317234 "dev": true,
318235 "requires": {
319236 "minipass": "2.2.1"
329246 }
330247 },
331248 "mocha": {
332 "version": "3.5.3",
333 "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.3.tgz",
334 "integrity": "sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg==",
249 "version": "4.0.1",
250 "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.0.1.tgz",
251 "integrity": "sha512-evDmhkoA+cBNiQQQdSKZa2b9+W2mpLoj50367lhy+Klnx9OV8XlCIhigUnn1gaTFLQCa0kdNhEGDr0hCXOQFDw==",
335252 "dev": true,
336253 "requires": {
337254 "browser-stdout": "1.3.0",
338 "commander": "2.9.0",
339 "debug": "2.6.8",
340 "diff": "3.2.0",
255 "commander": "2.11.0",
256 "debug": "3.1.0",
257 "diff": "3.3.1",
341258 "escape-string-regexp": "1.0.5",
342 "glob": "7.1.1",
343 "growl": "1.9.2",
259 "glob": "7.1.2",
260 "growl": "1.10.3",
344261 "he": "1.1.1",
345 "json3": "3.3.2",
346 "lodash.create": "3.1.1",
347262 "mkdirp": "0.5.1",
348 "supports-color": "3.1.2"
263 "supports-color": "4.4.0"
349264 }
350265 },
351266 "ms": {
382297 "dev": true,
383298 "requires": {
384299 "acorn": "5.1.2",
385 "minizlib": "1.0.3",
300 "minizlib": "1.0.4",
386301 "semver": "5.4.1"
302 },
303 "dependencies": {
304 "acorn": {
305 "version": "5.1.2",
306 "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.1.2.tgz",
307 "integrity": "sha512-o96FZLJBPY1lvTuJylGA9Bk3t/GKPPJG8H0ydQQl01crzwJgspa4AEIq/pVTXigmK0PHVQhiAtn8WMBLL9D2WA==",
308 "dev": true
309 }
387310 }
388311 },
389312 "semver": {
393316 "dev": true
394317 },
395318 "supports-color": {
396 "version": "3.1.2",
397 "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz",
398 "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=",
399 "dev": true,
400 "requires": {
401 "has-flag": "1.0.0"
319 "version": "4.4.0",
320 "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz",
321 "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==",
322 "dev": true,
323 "requires": {
324 "has-flag": "2.0.0"
402325 }
403326 },
404327 "to-fast-properties": {
1717 "transformation",
1818 "syntax"
1919 ],
20 "version": "0.9.14",
20 "version": "0.10.1",
2121 "homepage": "http://github.com/benjamn/ast-types",
2222 "repository": {
2323 "type": "git",
3131 "dependencies": {},
3232 "devDependencies": {
3333 "babel-types": "^6.26.0",
34 "babylon": "^6.16.1",
34 "babylon": "^7.0.0-beta.31",
3535 "espree": "^3.1.7",
3636 "esprima": "~4.0.0",
3737 "esprima-fb": "~14001.1.0-dev-harmony-fb",
38 "mocha": "^3.4.2",
38 "mocha": "^4.0.1",
3939 "reify": "^0.12.0"
4040 },
4141 "engines": {
+2286
-2221
test/run.js less more
1616
1717 var reifyBabylonParse = require("reify/lib/parsers/babylon.js").parse;
1818 function babylonParse(source) {
19 var ast = reifyBabylonParse(source);
20 if (ast.type === "File") ast = ast.program;
21 return ast;
19 var ast = reifyBabylonParse(source);
20 if (ast.type === "File") ast = ast.program;
21 return ast;
2222 }
2323
2424 describe("basic type checking", function() {
25 var fooId = b.identifier("foo");
26 var ifFoo = b.ifStatement(fooId, b.blockStatement([
27 b.expressionStatement(b.callExpression(fooId, []))
28 ]));
29
30 it("should exhibit sanity", function() {
31 assert.ok(n.IfStatement.check(ifFoo));
32 assert.ok(n.Statement.check(ifFoo));
33 assert.ok(n.Node.check(ifFoo));
34
35 assert.ok(n.BlockStatement.check(ifFoo.consequent));
36 assert.strictEqual(
37 ifFoo.consequent.body[0].expression.arguments.length,
38 0);
39
40 assert.strictEqual(ifFoo.test, fooId);
41 assert.ok(n.Expression.check(ifFoo.test));
42 assert.ok(n.Identifier.check(ifFoo.test));
43 assert.ok(!n.Statement.check(ifFoo.test));
44 assert.equal(
45 b.importDeclaration(
46 [b.importDefaultSpecifier(b.identifier("foo"))], b.literal("bar")
47 ).importKind,
48 "value"
25 var fooId = b.identifier("foo");
26 var ifFoo = b.ifStatement(fooId, b.blockStatement([
27 b.expressionStatement(b.callExpression(fooId, []))
28 ]));
29
30 it("should exhibit sanity", function() {
31 assert.ok(n.IfStatement.check(ifFoo));
32 assert.ok(n.Statement.check(ifFoo));
33 assert.ok(n.Node.check(ifFoo));
34
35 assert.ok(n.BlockStatement.check(ifFoo.consequent));
36 assert.strictEqual(
37 ifFoo.consequent.body[0].expression.arguments.length,
38 0);
39
40 assert.strictEqual(ifFoo.test, fooId);
41 assert.ok(n.Expression.check(ifFoo.test));
42 assert.ok(n.Identifier.check(ifFoo.test));
43 assert.ok(!n.Statement.check(ifFoo.test));
44 assert.equal(
45 b.importDeclaration(
46 [b.importDefaultSpecifier(b.identifier("foo"))], b.literal("bar")
47 ).importKind,
48 "value"
49 );
50 assert.throws(function () {
51 b.importDeclaration(
52 [b.importDefaultSpecifier(b.identifier("foo"))],
53 b.literal("bar"),
54 "baz"
55 )
56 });
57 assert.ok(n.ImportDeclaration.check(
58 b.importDeclaration(
59 [b.importDefaultSpecifier(b.identifier("foo"))], b.literal("bar"),
60 "type")
61 ));
62 assert.ok(n.ImportDeclaration.check(
63 b.importDeclaration(
64 [b.importNamespaceSpecifier(b.identifier("foo"))], b.literal("bar"))
65 ));
66 });
67 });
68
69 describe("isSupertypeOf", function() {
70 it("should report correct supertype relationships", function() {
71 var def = types.Type.def;
72
73 assert.ok(def("Node").isSupertypeOf(def("Node")));
74 assert.ok(def("Node").isSupertypeOf(def("Expression")));
75 assert.ok(!def("Expression").isSupertypeOf(def("Node")));
76 assert.ok(!def("Expression").isSupertypeOf(
77 def("DebuggerStatement")));
78
79 // TODO Make this test case more exhaustive.
80 });
81 });
82
83 describe("supertype lookup", function() {
84 it("should resolve the most precise supertypes", function() {
85 var table = types.use(require("../lib/types")).computeSupertypeLookupTable({
86 Function: true,
87 Declaration: true,
88 ArrowFunctionExpression: true,
89 Expression: true,
90 Identifier: true
91 });
92
93 function check(subtype, expectedSupertype) {
94 assert.strictEqual(table[subtype], expectedSupertype);
95 }
96
97 check("FunctionExpression", "Function");
98 check("FunctionDeclaration", "Function");
99 check("VariableDeclaration", "Declaration");
100 check("Identifier", "Identifier");
101 check("ArrowFunctionExpression", "ArrowFunctionExpression");
102 check("ForInStatement");
103 check("Node");
104 check("ThisExpression", "Expression");
105 check("Property");
106 });
107
108 it("should properly linearize the inheritance hierarchy", function() {
109 assert.deepEqual(
110 types.getSupertypeNames("FunctionExpression"),
111 ["Function", "Expression", "Pattern", "Node", "Printable"]
112 );
113 });
114
115 it("should trigger an AssertionError for unknown types", function() {
116 assert.throws(function() {
117 types.getSupertypeNames("AlienBoomerangDeclaration");
118 });
119 });
120 });
121
122 describe("shallow and deep checks", function() {
123 var index = b.identifier("foo");
124 var decl = b.variableDeclaration("var", [
125 b.variableDeclarator(
126 index,
127 b.literal(42)
128 )
129 ]);
130
131 it("should work when shallow", function() {
132 assert.ok(n.Node.check(decl));
133 assert.ok(n.Statement.check(decl));
134 assert.ok(n.Declaration.check(decl));
135 assert.ok(n.VariableDeclaration.check(decl));
136 });
137
138 it("should work when deep", function() {
139 assert.ok(n.Node.check(decl, true));
140 assert.ok(n.Statement.check(decl, true));
141 assert.ok(n.Declaration.check(decl, true));
142 assert.ok(n.VariableDeclaration.check(decl, true));
143 });
144
145 it("should fail when expected", function() {
146 // Not an Expression.
147 assert.ok(!n.Expression.check(decl));
148
149 // This makes decl cease to conform to n.VariableDeclaration.
150 decl.declarations.push(b.literal("bar"));
151
152 assert.ok(n.Node.check(decl));
153 assert.ok(n.Statement.check(decl));
154 assert.ok(n.Declaration.check(decl));
155 assert.ok(n.VariableDeclaration.check(decl));
156
157 assert.ok(!n.Node.check(decl, true));
158 assert.ok(!n.Statement.check(decl, true));
159 assert.ok(!n.Declaration.check(decl, true));
160
161 // As foretold above.
162 assert.ok(!n.VariableDeclaration.check(decl, true));
163
164 // Still not an Expression.
165 assert.ok(!n.Expression.check(decl));
166 });
167
168 var fs = b.forStatement(
169 decl,
170 b.binaryExpression("<", index, b.literal(48)),
171 b.updateExpression("++", index, true),
172 b.blockStatement([
173 b.expressionStatement(
174 b.callExpression(index, [])
175 )
176 ])
177 );
178
179 it("should disagree according to depth", function() {
180 assert.ok(n.Node.check(fs));
181 assert.ok(n.Statement.check(fs));
182 assert.ok(n.ForStatement.check(fs));
183
184 // Not a true ForStatement because fs.init is not a true
185 // VariableDeclaration.
186 assert.ok(!n.Node.check(fs, true));
187 assert.ok(!n.Statement.check(fs, true));
188 assert.ok(!n.ForStatement.check(fs, true));
189 });
190 });
191
192 function validateProgram(file) {
193 var fullPath = path.join(__dirname, "..", file);
194
195 it("should validate " + file + " with Esprima", function(done) {
196 var parse = require("esprima").parse;
197
198 fs.readFile(fullPath, "utf8", function(err, code) {
199 if (err) throw err;
200
201 n.Program.assert(parse(code), true);
202 n.Program.assert(parse(code, { loc: true }), true);
203
204 done();
205 });
206 });
207
208 it("should validate " + file + " with Babel", function(done) {
209 fs.readFile(fullPath, "utf8", function(err, code) {
210 if (err) throw err;
211 var ast = babylonParse(code);
212 n.Program.assert(ast, true);
213 done();
214 });
215 });
216 }
217
218 describe("whole-program validation", function() {
219 this.timeout(20000);
220
221 validateProgram("main.js");
222 validateProgram("lib/shared.js");
223 validateProgram("def/core.js");
224 validateProgram("lib/types.js");
225 validateProgram("test/run.js");
226 validateProgram("test/data/backbone.js");
227 validateProgram("test/data/jquery-1.9.1.js");
228 });
229
230 describe("esprima Syntax types", function() {
231 var def = types.Type.def;
232 var typeNames = {};
233
234 function addTypeName(name) {
235 typeNames[name] = name;
236 }
237
238 Object.keys(require("esprima").Syntax).forEach(addTypeName);
239 Object.keys(require("esprima-fb").Syntax).forEach(addTypeName);
240 Object.keys(
241 require("babel-types").VISITOR_KEYS
242 ).forEach(addTypeName);
243
244 it("should all be buildable", function() {
245 Object.keys(typeNames).forEach(function(name) {
246 assert.ok(hasOwn.call(n, name), name);
247 assert.strictEqual(def(name).buildable, true, name);
248 });
249 });
250
251 it("builders for subtypes of Expression should have equivalent ExpressionStatement builders", function() {
252 Object.keys(typeNames).forEach(function(name) {
253 if (def(name).buildable &&
254 def("Expression").isSupertypeOf(def(name))) {
255 var statementBuilderName = rawTypes.getStatementBuilderName(name);
256 assert.ok(b[statementBuilderName], name + ":" +statementBuilderName);
257 }
258 });
259
260 // sanity check
261 var expStmt = b.assignmentStatement("=", b.identifier("a"), b.identifier("b"));
262 assert.strictEqual(expStmt.type, "ExpressionStatement");
263 });
264 });
265
266 describe("types.getFieldValue", function() {
267 it("should work for explicit fields", function() {
268 assert.strictEqual(
269 types.getFieldValue({
270 type: "CatchClause"
271 }, "type"),
272 "CatchClause"
273 );
274
275 assert.strictEqual(
276 types.getFieldValue({
277 type: "CatchClause",
278 guard: b.identifier("test")
279 }, "guard").name,
280 "test"
281 );
282 });
283
284 it("should work for implicit/default fields", function() {
285 assert.strictEqual(
286 types.getFieldValue({
287 type: "CatchClause"
288 }, "guard"),
289 null
290 );
291
292 assert.strictEqual(
293 types.getFieldValue({
294 type: "CatchClause"
295 }, "asdf"),
296 void 0
297 );
298
299 assert.deepEqual(
300 types.getFieldValue({
301 type: "TryStatement",
302 }, "handler"),
303 null
304 );
305
306 assert.deepEqual(
307 types.getFieldValue({
308 type: "TryStatement",
309 }, "handlers"),
310 []
311 );
312
313 assert.deepEqual(
314 types.getFieldValue({
315 type: "TryStatement",
316 }, "guardedHandlers"),
317 []
318 );
319 });
320
321 it("should work for explicitly undefined fields", function() {
322 assert.deepEqual(
323 types.getFieldValue({
324 type: "TryStatement",
325 guardedHandlers: void 0
326 }, "guardedHandlers"),
327 []
328 );
329 });
330
331 it("should handle undefined objects", function() {
332 assert.equal(
333 types.getFieldValue(undefined, "name"),
334 undefined
335 );
336 });
337 });
338
339 describe("types.eachField", function() {
340 var context = {};
341
342 function check(node, names) {
343 var seen = [];
344
345 types.eachField(node, function(name, value) {
346 assert.strictEqual(this, context);
347 if (name === "type")
348 assert.strictEqual(node.type, value);
349 seen.push(name);
350 }, context);
351
352 assert.deepEqual(seen.sort(), names.sort());
353 }
354
355 it("should give correct keys for supertypes", function() {
356 check({ type: "Expression" }, ["type"]);
357 });
358
359 it("should work for non-buildable types", function() {
360 check({ type: "Position" }, [
361 "type", "line", "column"
362 ]);
363
364 check({ type: "SourceLocation" }, [
365 "type", "start", "end", "source"
366 ]);
367 });
368
369 it("should respect hidden fields", function() {
370 check({ type: "TryStatement" }, [
371 // Note that the "handlers" field is now hidden from eachField.
372 "type", "block", "handler", "guardedHandlers", "finalizer"
373 ]);
374 });
375
376 check({ type: "CatchClause" }, [
377 "type", "param", "guard", "body"
378 ]);
379
380 it("should complain about invalid types", function() {
381 assert.throws(function() {
382 check({ type: "asdf" }, ["type"]);
383 }, "did not recognize object of type " + JSON.stringify("asdf"));
384 });
385
386 it("should infer SourceLocation types", function() {
387 check({
388 line: 10,
389 column: 37
390 }, ["line", "column"]);
391 });
392 });
393
394 describe("types.visit", function() {
395 var call = b.expressionStatement(
396 b.callExpression(
397 b.memberExpression(
398 b.identifier("foo"),
399 b.identifier("bar"),
400 false
401 ),
402 [b.literal("baz")]
403 )
404 );
405
406 var ts = b.tryStatement(
407 b.blockStatement([call, call]),
408 b.catchClause(
409 b.identifier("err"),
410 null,
411 b.blockStatement([])
412 )
413 );
414
415 it("should have correct .parent path", function() {
416 var literalCount = 0;
417
418 n.TryStatement.assert(types.visit(ts, {
419 visitLiteral: function(path) {
420 var node = path.node;
421 literalCount += 1;
422 assert.strictEqual(node.value, "baz");
423 assert.strictEqual(path.parent.node, call.expression);
424 assert.strictEqual(path.parent.parent.node, call);
425 assert.strictEqual(path.parent.parent.parent.node, ts.block);
426 assert.strictEqual(path.parent.parent.parent.parent.node, ts);
427 assert.strictEqual(path.parent.parent.parent.parent.parent, null);
428 this.traverse(path);
429 }
430 }), true);
431
432 assert.strictEqual(literalCount, 2);
433 });
434
435 it("should abort subtree traversal when false returned", function() {
436 var ids = {};
437
438 types.visit(ts, {
439 visitMemberExpression: function(path) {
440 return false;
441 },
442
443 visitIdentifier: function(path) {
444 ids[path.node.name] = true;
445 this.traverse(path);
446 }
447 });
448
449 // Make sure all identifers beneath member expressions were skipped.
450 assert.deepEqual(ids, { err: true });
451
452 ids = {};
453
454 types.visit(ts, {
455 visitIdentifier: function(path) {
456 ids[path.node.name] = true;
457 this.traverse(path);
458 }
459 });
460
461 // Now make sure those identifiers (foo and bar) were visited.
462 assert.deepEqual(ids, {
463 err: true,
464 foo: true,
465 bar: true
466 });
467 });
468
469 it("this.abort() should abort entire traversal", function() {
470 var literal = "not visited";
471 var unvisitedTypes = [];
472 var root = types.visit(call, {
473 visitIdentifier: function(path) {
474 if (path.value.name === "foo") {
475 this.abort();
476 }
477 },
478
479 visitLiteral: function(path) {
480 literal = path.value;
481 this.traverse(path);
482 },
483
484 visitNode: function(path) {
485 unvisitedTypes.push(path.value.type);
486 this.traverse(path);
487 }
488 });
489
490 assert.strictEqual(root, call);
491 assert.strictEqual(literal, "not visited");
492 assert.deepEqual(unvisitedTypes, [
493 "ExpressionStatement",
494 "CallExpression",
495 "MemberExpression"
496 ]);
497 });
498
499 it("this.abort() should be cancelable", function() {
500 var literal = "not visited";
501 var unvisitedTypes = [];
502 var root = types.visit(call, {
503 visitIdentifier: function(path) {
504 if (path.value.name === "foo") {
505 this.abort();
506 }
507 },
508
509 visitMemberExpression: function(path) {
510 try {
511 this.traverse(path);
512 } catch (err) {
513 assert.ok(err instanceof this.AbortRequest);
514 err.cancel();
515 }
516 },
517
518 visitLiteral: function(path) {
519 literal = path.value;
520 this.traverse(path);
521 },
522
523 visitNode: function(path) {
524 unvisitedTypes.push(path.value.type);
525 this.traverse(path);
526 }
527 });
528
529 assert.strictEqual(root, call);
530
531 n.Literal.assert(literal);
532 assert.strictEqual(literal.value, "baz");
533 assert.strictEqual(literal, call.expression.arguments[0]);
534
535 assert.deepEqual(unvisitedTypes, [
536 "ExpressionStatement",
537 "CallExpression"
538 // Note that the MemberExpression and the Literal were visited
539 // by their type-specific methods, so they were not visited by
540 // the catch-all visitNode method.
541 ]);
542 });
543
544 it("should visit comments", function() {
545 var ast = parse([
546 "function getArgs(/*arguments*/) {",
547 " // Turn arguments into an array.",
548 " return Array.prototype.slice.call(arguments);",
549 "}"
550 ].join("\n"), {
551 comment: true
552 });
553
554 var blockComments = [];
555 var lineComments = [];
556
557 types.visit(ast, {
558 visitComment: function(path) {
559 this.traverse(path);
560 if (n.Block.check(path.value)) {
561 blockComments.push(path.value);
562 } else if (n.Line.check(path.value)) {
563 lineComments.push(path.value);
564 }
565 }
566 });
567
568 assert.strictEqual(blockComments.length, 1);
569 assert.strictEqual(blockComments[0].value, "arguments");
570
571 assert.strictEqual(lineComments.length, 1);
572 assert.strictEqual(
573 lineComments[0].value,
574 " Turn arguments into an array."
575 );
576
577 blockComments.length = 0;
578 lineComments.length = 0;
579
580 types.visit(ast, {
581 visitBlock: function(path) {
582 blockComments.push(path.value);
583 this.traverse(path);
584 }
585 });
586
587 assert.strictEqual(blockComments.length, 1);
588 assert.strictEqual(blockComments[0].value, "arguments");
589
590 assert.strictEqual(lineComments.length, 0);
591
592 blockComments.length = 0;
593 lineComments.length = 0;
594
595 types.visit(ast, {
596 visitLine: function(path) {
597 lineComments.push(path.value);
598 this.traverse(path);
599 }
600 });
601
602 assert.strictEqual(blockComments.length, 0);
603
604 assert.strictEqual(lineComments.length, 1);
605 assert.strictEqual(
606 lineComments[0].value,
607 " Turn arguments into an array."
608 );
609
610 blockComments.length = 0;
611 lineComments.length = 0;
612
613 types.visit(ast, {
614 visitBlock: function(path) {
615 blockComments.push(path.value);
616 this.traverse(path);
617 },
618
619 visitLine: function(path) {
620 lineComments.push(path.value);
621 this.traverse(path);
622 }
623 });
624
625 assert.strictEqual(blockComments.length, 1);
626 assert.strictEqual(blockComments[0].value, "arguments");
627
628 assert.strictEqual(lineComments.length, 1);
629 assert.strictEqual(
630 lineComments[0].value,
631 " Turn arguments into an array."
632 );
633 });
634 });
635
636 describe("path traversal", function() {
637 var call = b.expressionStatement(
638 b.callExpression(
639 b.memberExpression(
640 b.identifier("foo"),
641 b.identifier("bar"),
642 false
643 ),
644 [b.literal("baz")]
645 )
646 );
647
648 it("should accept root paths as well as AST nodes", function() {
649 var path = new NodePath(call).get("expression", "callee");
650 var idCount = 0;
651
652 // Note that we're passing a path instead of a node as the first
653 // argument to types.traverse.
654 types.visit(path, {
655 visitIdentifier: function(path) {
656 var node = path.node;
657 ++idCount;
658
659 if (node.name === "bar") {
660 n.MemberExpression.assert(path.parent.node);
661 n.CallExpression.assert(path.parent.parent.node);
662 n.ExpressionStatement.assert(path.parent.parent.parent.node);
663 }
664
665 this.traverse(path);
666 }
667 });
668
669 assert.strictEqual(idCount, 2);
670 });
671 });
672
673 describe("replacing the root", function() {
674 var ast = b.expressionStatement(
675 b.unaryExpression("!", b.sequenceExpression([
676 b.identifier("a"),
677 b.identifier("b"),
678 b.identifier("c")
679 ]))
680 );
681
682 it("should be possible", function() {
683 var callExp = types.visit(ast, {
684 visitExpressionStatement: function(path) {
685 path.replace(b.callExpression(b.identifier("f"), [
686 path.node.expression
687 ]));
688
689 this.traverse(path);
690 }
691 });
692
693 n.CallExpression.assert(callExp, true);
694 });
695 });
696
697 describe("NodePath", function() {
698 it("should have the expected type hierarchy", function() {
699 assert.strictEqual(new Path({}).constructor, Path);
700
701 var np = new NodePath(b.identifier("foo"));
702 assert.strictEqual(np.constructor, NodePath);
703 assert.ok(np.get("name") instanceof NodePath);
704 });
705
706 var ast = b.expressionStatement(
707 b.unaryExpression("!", b.sequenceExpression([
708 b.identifier("a"),
709 b.identifier("b"),
710 b.identifier("c")
711 ]))
712 );
713
714 var path = new NodePath(ast);
715
716 it("should have sane values, nodes, parents", function() {
717 var opPath = path.get("expression", "operator");
718 assert.strictEqual(opPath.value, "!");
719 assert.strictEqual(opPath.node, ast.expression);
720 assert.strictEqual(opPath.parent, path);
721 assert.strictEqual(opPath.parent.node, ast);
722 });
723
724 var binaryYield = b.expressionStatement(
725 b.logicalExpression(
726 "&&",
727 b.yieldExpression(b.identifier("a"), false),
728 b.yieldExpression(b.identifier("b"), true)
729 )
730 );
731
732 it("should support .needsParens()", function() {
733 var argPath = path.get("expression", "argument");
734 assert.ok(argPath.needsParens());
735
736 var exprsPath = argPath.get("expressions");
737 assert.ok(!exprsPath.needsParens());
738 assert.strictEqual(exprsPath.get("length").value, 3);
739 assert.ok(!exprsPath.get(1).needsParens());
740
741 var byPath = new NodePath(binaryYield);
742 assert.ok(!byPath.get("expression").needsParens());
743 assert.ok(byPath.get("expression", "left").needsParens());
744 assert.ok(byPath.get("expression", "right").needsParens());
745
746 var sequenceAssignmentAST = b.assignmentExpression(
747 '=',
748 b.identifier('a'),
749 b.sequenceExpression([b.literal(1), b.literal(2)])
750 );
751
752 var sequenceAssignmentPath = new NodePath(sequenceAssignmentAST);
753 assert.ok(sequenceAssignmentPath.get("right").needsParens());
754 });
755
756 it("should support .needsParens(true)", function() {
757 var programPath = new NodePath(parse("(function(){})"));
758 var funExpPath = programPath.get("body", 0, "expression");
759 n.FunctionExpression.assert(funExpPath.value);
760 assert.strictEqual(funExpPath.needsParens(), true);
761 assert.strictEqual(funExpPath.canBeFirstInStatement(), false);
762 assert.strictEqual(funExpPath.firstInStatement(), true);
763 assert.strictEqual(funExpPath.needsParens(true), false);
764
765 programPath = new NodePath(parse("({ foo: 42 })"));
766 var objLitPath = programPath.get("body", 0, "expression");
767 n.ObjectExpression.assert(objLitPath.value);
768 assert.strictEqual(objLitPath.needsParens(), true);
769 assert.strictEqual(objLitPath.canBeFirstInStatement(), false);
770 assert.strictEqual(objLitPath.firstInStatement(), true);
771 assert.strictEqual(objLitPath.needsParens(true), false);
772 });
773
774 it("should prune redundant variable declaration nodes", function() {
775 var programPath = new NodePath(parse("(function(){var y = 1,x = 2;})"));
776 var funBlockStatementPath = programPath.get("body", 0, "expression", "body");
777 var variableDeclaration = funBlockStatementPath.get("body", 0);
778 var yVariableDeclaratorPath = variableDeclaration.get("declarations", 0);
779 var xVariableDeclaratorPath = variableDeclaration.get("declarations", 1);
780
781 n.VariableDeclarator.assert(yVariableDeclaratorPath.node);
782 n.VariableDeclarator.assert(xVariableDeclaratorPath.node);
783
784 var remainingNodePath = yVariableDeclaratorPath.prune();
785
786 assert.strictEqual(remainingNodePath, variableDeclaration);
787
788 remainingNodePath = xVariableDeclaratorPath.prune();
789
790 assert.strictEqual(remainingNodePath, funBlockStatementPath);
791 assert.strictEqual(funBlockStatementPath.get("body", 0).value, undefined);
792 });
793
794 it("should prune redundant expression statement nodes", function() {
795 var programPath = new NodePath(parse("(function(){key = 'value';})"));
796 var funBlockStatementPath = programPath.get("body", 0, "expression", "body");
797 var assignmentExpressionPath = funBlockStatementPath.get("body", 0, "expression");
798
799 n.AssignmentExpression.assert(assignmentExpressionPath.node);
800
801 var remainingNodePath = assignmentExpressionPath.prune();
802
803 assert.strictEqual(remainingNodePath, funBlockStatementPath);
804 assert.strictEqual(funBlockStatementPath.value.body.length, 0);
805 });
806
807 it("should prune redundant if statement node if no consequent and alternate remain after prune", function() {
808 var programPath = new NodePath(parse("if(true){var t = 0;}"));
809 var consequentNodePath = programPath.get("body", 0, "consequent");
810
811 n.BlockStatement.assert(consequentNodePath.node);
812
813 var remainingNodePath = consequentNodePath.prune();
814
815 var testExpressionNodePath = programPath.get("body", 0);
816
817 n.ExpressionStatement.assert(remainingNodePath.node);
818 assert.strictEqual(remainingNodePath, testExpressionNodePath);
819 });
820
821 it("should modify if statement node if consequent is pruned and alternate remains", function() {
822 var programPath = new NodePath(parse("if(x > 10){var t = 0;}else{var f = 2;}"));
823 var consequentNodePath = programPath.get("body", 0, "consequent");
824
825 n.BlockStatement.assert(consequentNodePath.node);
826
827 var remainingNodePath = consequentNodePath.prune();
828
829 var modifiedIfStatementNodePath = programPath.get("body", 0);
830 var negatedTestExpression = modifiedIfStatementNodePath.get("test");
831
832 n.IfStatement.assert(remainingNodePath.node);
833 n.UnaryExpression.assert(negatedTestExpression.node);
834 assert.strictEqual(remainingNodePath, modifiedIfStatementNodePath);
835 assert.strictEqual(negatedTestExpression.node.operator, "!");
836 });
837
838 it("should modify if statement node if consequent is pruned, alternate remains with no double negation", function() {
839 var programPath = new NodePath(parse("if(!condition){var t = 0;}else{var f = 2;}"));
840 var consequentNodePath = programPath.get("body", 0, "consequent");
841
842 n.BlockStatement.assert(consequentNodePath.node);
843
844 var remainingNodePath = consequentNodePath.prune();
845
846 var modifiedIfStatementNodePath = programPath.get("body", 0);
847 var testExpression = modifiedIfStatementNodePath.get("test");
848
849 n.IfStatement.assert(remainingNodePath.node);
850 n.Identifier.assert(testExpression.node);
851 assert.strictEqual(remainingNodePath, modifiedIfStatementNodePath);
852 });
853 });
854
855 describe("path.replace", function() {
856 var ast;
857
858 beforeEach(function() {
859 ast = b.functionDeclaration(
860 b.identifier("fn"),
861 [],
862 b.blockStatement([
863 b.variableDeclaration(
864 "var",
865 [b.variableDeclarator(b.identifier("a"), null)]
866 )
867 ])
868 );
869 });
870
871 it("should support replacement with a single node", function() {
872 types.visit(ast, {
873 visitIdentifier: function(path) {
874 if (path.node.name === "a") {
875 path.replace(b.identifier("b"));
876 }
877 this.traverse(path);
878 }
879 });
880
881 assert.equal(ast.body.body[0].declarations[0].id.name, "b");
882 });
883
884 it("should support replacement in an array with a single node", function() {
885 types.visit(ast, {
886 visitVariableDeclaration: function(path) {
887 path.replace(b.returnStatement(null));
888 this.traverse(path);
889 }
890 });
891
892 assert.equal(ast.body.body.length, 1);
893 assert.ok(n.ReturnStatement.check(ast.body.body[0]));
894 });
895
896 it("should support replacement with nothing", function() {
897 types.visit(ast, {
898 visitVariableDeclaration: function(path) {
899 path.replace();
900 this.traverse(path);
901 }
902 });
903
904 assert.equal(ast.body.body.length, 0);
905 });
906
907 it("should support replacement with itself plus more in an array", function() {
908 types.visit(ast, {
909 visitVariableDeclaration: function(path) {
910 var scopeBody = path.scope.path.get("body", "body");
911
912 // This is contrived such that we just happen to be replacing
913 // the same node we're currently processing, perhaps using a
914 // helper function to create variables at the top of the scope.
915 assert.strictEqual(scopeBody.get(0), path);
916
917 // Prepend `var $$;` inside the block. This should update our
918 // `this` NodePath to correct its array index so that a
919 // subsequent replace will still work.
920 scopeBody.get(0).replace(
921 b.variableDeclaration(
922 "var",
923 [b.variableDeclarator(b.identifier("$$"), null)]
924 ),
925 scopeBody.get(0).value
49926 );
50 assert.throws(function () {
51 b.importDeclaration(
52 [b.importDefaultSpecifier(b.identifier("foo"))],
53 b.literal("bar"),
54 "baz"
927
928 // Now do it again to make sure all the other indexes are
929 // updated, too.
930 scopeBody.get(0).replace(
931 b.variableDeclaration(
932 "var",
933 [b.variableDeclarator(b.identifier("$2"), null)]
934 ),
935 scopeBody.get(0).value
936 );
937
938 assert.strictEqual(scopeBody.get(0), path);
939
940 // Then replace the node, not the one we just added.
941 return b.returnStatement(b.identifier("$3"));
942 }
943 });
944
945 var statements = ast.body.body;
946 assert.deepEqual(
947 statements.map(function(node) { return node.type; }),
948 ['ReturnStatement', 'VariableDeclaration', 'VariableDeclaration']
949 );
950
951 n.ReturnStatement.assert(statements[0]);
952 assert.equal(statements[0].argument.name, "$3");
953
954 n.VariableDeclaration.assert(statements[1]);
955 assert.equal(statements[1].declarations[0].id.name, "$$");
956
957 n.VariableDeclaration.assert(statements[2]);
958 assert.equal(statements[2].declarations[0].id.name, "a");
959 });
960
961 it("should not throw when replacing the same node twice", function() {
962 types.visit(ast, {
963 visitVariableDeclaration: function(path) {
964 path.replace(b.expressionStatement(b.literal(null)));
965 n.ExpressionStatement.assert(path.value);
966 n.Literal.assert(path.value.expression);
967 assert.strictEqual(path.value.expression.value, null);
968
969 path.replace(b.expressionStatement(b.literal("OK")));
970 n.ExpressionStatement.assert(path.value);
971 n.Literal.assert(path.value.expression);
972 assert.strictEqual(path.value.expression.value, "OK");
973
974 if (path.parentPath.get(path.name) !== path) {
975 assert.ok(false, "Should have reused the same path");
976 }
977
978 this.traverse(path);
979 }
980 });
981 });
982 });
983
984 describe("global scope", function() {
985 var scope = [
986 "var foo = 42;",
987 "function bar(baz) {",
988 " return baz + foo;",
989 "}"
990 ];
991
992 var ast = parse(scope.join("\n"));
993
994 it("should be reachable from nested scopes", function() {
995 var globalScope;
996
997 types.visit(ast, {
998 visitProgram: function(path) {
999 assert.strictEqual(path.scope.isGlobal, true);
1000 globalScope = path.scope;
1001 this.traverse(path);
1002 },
1003
1004 visitFunctionDeclaration: function(path) {
1005 var node = path.node;
1006 assert.strictEqual(path.scope.isGlobal, false);
1007
1008 assert.strictEqual(node.id.name, "bar");
1009 assert.notStrictEqual(path.scope, globalScope);
1010 assert.strictEqual(path.scope.isGlobal, false);
1011 assert.strictEqual(path.scope.parent, globalScope);
1012
1013 assert.strictEqual(path.scope.getGlobalScope(), globalScope);
1014
1015 this.traverse(path);
1016 }
1017 });
1018 });
1019
1020 it("should be found by .lookup and .declares", function() {
1021 var globalScope;
1022
1023 types.visit(ast, {
1024 visitProgram: function(path) {
1025 assert.strictEqual(path.scope.isGlobal, true);
1026 globalScope = path.scope;
1027 this.traverse(path);
1028 },
1029
1030 visitFunctionDeclaration: function(path) {
1031 assert.ok(globalScope.declares("foo"));
1032 assert.ok(globalScope.declares("bar"));
1033 assert.strictEqual(path.scope.lookup("foo"), globalScope);
1034 assert.strictEqual(path.scope.lookup("bar"), globalScope);
1035
1036 assert.ok(path.scope.declares("baz"));
1037 assert.strictEqual(path.scope.lookup("baz"), path.scope);
1038
1039 assert.strictEqual(path.scope.lookup("qux"), null);
1040 assert.strictEqual(globalScope.lookup("baz"), null);
1041
1042 this.traverse(path);
1043 }
1044 });
1045 });
1046 });
1047
1048 describe("scope methods", function () {
1049 var scope = [
1050 "var foo = 42;",
1051 "function bar(baz) {",
1052 " return baz + foo;",
1053 "}",
1054 "var nom = function rom(pom) {",
1055 " var zom;",
1056 " return rom(pom);",
1057 "};"
1058 ];
1059
1060 it("getBindings should get local and global scope bindings", function() {
1061 var ast = parse(scope.join("\n"));
1062 var checked = [];
1063
1064 types.visit(ast, {
1065 visitProgram: function(path) {
1066 var bindings = path.scope.getBindings();
1067 assert.deepEqual(["bar", "foo", "nom"], Object.keys(bindings).sort());
1068 assert.equal(1, bindings.foo.length);
1069 assert.equal(1, bindings.bar.length);
1070 checked.push(path.node);
1071 this.traverse(path);
1072 },
1073
1074 visitFunctionDeclaration: function(path) {
1075 var bindings = path.scope.getBindings();
1076 assert.deepEqual(["baz"], Object.keys(bindings));
1077 assert.equal(1, bindings.baz.length);
1078 checked.push(path.node);
1079 this.traverse(path);
1080 },
1081
1082 visitReturnStatement: function(path) {
1083 var node = path.node;
1084 if (n.CallExpression.check(node.argument) &&
1085 node.argument.callee.name === "rom") {
1086 var bindings = path.scope.getBindings();
1087 assert.deepEqual(["pom", "rom", "zom"], Object.keys(bindings).sort());
1088 checked.push(node);
1089 }
1090 this.traverse(path);
1091 }
1092 });
1093
1094 assert.deepEqual(
1095 checked.map(function(node) { return node.type; }),
1096 ['Program', 'FunctionDeclaration', 'ReturnStatement']
1097 );
1098 });
1099
1100 it("getBindings should work for import statements (esprima-fb)", function() {
1101 var ast = require("esprima-fb").parse(
1102 [
1103 "import {x, y as z} from 'xy';",
1104 "import xyDefault from 'xy';",
1105 "import * as xyNamespace from 'xy';"
1106 ].join("\n"),
1107 {sourceType: "module"}
1108 );
1109
1110 var names;
1111
1112 types.visit(ast, {
1113 visitProgram: function(path) {
1114 names = Object.keys(path.scope.getBindings()).sort();
1115 this.traverse(path);
1116 }
1117 });
1118
1119 assert.deepEqual(names, ["x", "xyDefault", "xyNamespace", "z"]);
1120 });
1121
1122 it("getBindings should work for import statements (acorn)", function() {
1123 var ast = babylonParse([
1124 "import {x, y as z} from 'xy';",
1125 "import xyDefault from 'xy';",
1126 "import * as xyNamespace from 'xy';"
1127 ].join("\n"), {
1128 sourceType: "module",
1129 ecmaVersion: 6
1130 });
1131
1132 var names;
1133
1134 types.visit(ast, {
1135 visitProgram: function(path) {
1136 names = Object.keys(path.scope.getBindings()).sort();
1137 this.traverse(path);
1138 }
1139 });
1140
1141 assert.deepEqual(names, ["x", "xyDefault", "xyNamespace", "z"]);
1142 });
1143
1144 it("should work for ES6 syntax (espree)", function() {
1145 var names;
1146
1147 var ast = require("espree").parse([
1148 "var zap;",
1149 "export default function(zom) {",
1150 " var innerFn = function(zip) {};",
1151 " return innerFn(zom);",
1152 "};"
1153 ].join("\n"), {
1154 sourceType: "module",
1155 ecmaVersion: 6
1156 });
1157
1158 types.visit(ast, {
1159 visitFunctionDeclaration: function(path) {
1160 names = Object.keys(path.scope.lookup("zap").getBindings()).sort();
1161 assert.deepEqual(names, ["zap"]);
1162 this.traverse(path);
1163 }
1164 });
1165 });
1166
1167 it("should inject temporary into current scope", function() {
1168 var ast = parse(scope.join("\n"));
1169 var bindings;
1170
1171 types.visit(ast, {
1172 visitProgram: function(path) {
1173 path.scope.injectTemporary();
1174 bindings = path.scope.getBindings();
1175 assert.deepEqual(["bar", "foo", "nom", "t$0$0"], Object.keys(bindings).sort());
1176 this.traverse(path);
1177 },
1178
1179 visitFunctionDeclaration: function(path) {
1180 path.scope.injectTemporary(
1181 path.scope.declareTemporary("t$")
1182 )
1183 bindings = path.scope.getBindings();
1184 assert.deepEqual(["baz", "t$1$0"], Object.keys(bindings));
1185 this.traverse(path);
1186 }
1187 });
1188 });
1189
1190 it("declareTemporary should use distinct names in nested scopes", function() {
1191 var ast = parse(scope.join("\n"));
1192 var globalVarDecl;
1193 var barVarDecl;
1194 var romVarDecl;
1195
1196 types.visit(ast, {
1197 visitProgram: function(path) {
1198 path.get("body").unshift(
1199 globalVarDecl = b.variableDeclaration("var", [
1200 b.variableDeclarator(
1201 path.scope.declareTemporary("$"),
1202 b.literal("global")
1203 ),
1204 b.variableDeclarator(
1205 path.scope.declareTemporary("$"),
1206 b.literal("global")
551207 )
1208 ])
1209 );
1210
1211 this.traverse(path);
1212 },
1213
1214 visitFunction: function(path) {
1215 var funcId = path.value.id;
1216
1217 var varDecl = b.variableDeclaration("var", [
1218 b.variableDeclarator(
1219 path.scope.declareTemporary("$"),
1220 b.literal(funcId.name + 1)
1221 ),
1222 b.variableDeclarator(
1223 path.scope.declareTemporary("$"),
1224 b.literal(funcId.name + 2)
1225 )
1226 ]);
1227
1228 path.get("body", "body").unshift(varDecl);
1229
1230 if (funcId.name === "bar") {
1231 barVarDecl = varDecl;
1232 } else if (funcId.name === "rom") {
1233 romVarDecl = varDecl;
1234 }
1235
1236 this.traverse(path);
1237 }
1238 });
1239
1240 assert.strictEqual(globalVarDecl.declarations[0].id.name, "$0$0");
1241 assert.strictEqual(globalVarDecl.declarations[1].id.name, "$0$1");
1242 assert.strictEqual(barVarDecl.declarations[0].id.name, "$1$0");
1243 assert.strictEqual(barVarDecl.declarations[1].id.name, "$1$1");
1244 assert.strictEqual(romVarDecl.declarations[0].id.name, "$1$0");
1245 assert.strictEqual(romVarDecl.declarations[1].id.name, "$1$1");
1246 });
1247 });
1248
1249 describe("catch block scope", function() {
1250 var catchWithVarDecl = [
1251 "function foo(e) {",
1252 " try {",
1253 " bar();",
1254 " } catch (e) {",
1255 " var f = e + 1;",
1256 " return function(g) {",
1257 " return e + g;",
1258 " };",
1259 " }",
1260 " return f;",
1261 "}"
1262 ];
1263
1264 var path = new NodePath(parse(catchWithVarDecl.join("\n")));
1265 var fooPath = path.get("body", 0);
1266 var fooScope = fooPath.scope;
1267 var catchPath = fooPath.get("body", "body", 0, "handler");
1268 var catchScope = catchPath.scope;
1269
1270 it("should not affect outer scope declarations", function() {
1271 n.FunctionDeclaration.assert(fooScope.node);
1272 assert.strictEqual(fooScope.declares("e"), true);
1273 assert.strictEqual(fooScope.declares("f"), true);
1274 assert.strictEqual(fooScope.lookup("e"), fooScope);
1275 });
1276
1277 it("should declare only the guard parameter", function() {
1278 n.CatchClause.assert(catchScope.node);
1279 assert.strictEqual(catchScope.declares("e"), true);
1280 assert.strictEqual(catchScope.declares("f"), false);
1281 assert.strictEqual(catchScope.lookup("e"), catchScope);
1282 assert.strictEqual(catchScope.lookup("f"), fooScope);
1283 });
1284
1285 it("should shadow only the parameter in nested scopes", function() {
1286 var closurePath = catchPath.get("body", "body", 1, "argument");
1287 var closureScope = closurePath.scope;
1288 n.FunctionExpression.assert(closureScope.node);
1289 assert.strictEqual(closureScope.declares("e"), false);
1290 assert.strictEqual(closureScope.declares("f"), false);
1291 assert.strictEqual(closureScope.declares("g"), true);
1292 assert.strictEqual(closureScope.lookup("g"), closureScope);
1293 assert.strictEqual(closureScope.lookup("e"), catchScope);
1294 assert.strictEqual(closureScope.lookup("f"), fooScope);
1295 });
1296 });
1297
1298 describe("array and object pattern scope", function() {
1299
1300 function scopeFromPattern(pattern) {
1301 return new NodePath(
1302 b.program([
1303 b.variableDeclaration('var', [
1304 b.variableDeclarator(pattern, null)
1305 ])
1306 ])
1307 ).scope;
1308 }
1309
1310 // ObjectPattern with Property and SpreadProperty
1311 // ArrayPattern with SpreadElement
1312 describe("esprima", function() {
1313 var types = require('../fork')([
1314 require("../def/esprima")
1315 ]);
1316 var b = types.builders;
1317
1318 var objectPattern;
1319 var arrayPattern;
1320
1321 beforeEach(function() {
1322 // {a, b: c, ...d}
1323 objectPattern = b.objectPattern([
1324 b.property('init', b.identifier('a'), b.identifier('a')),
1325 b.property('init', b.identifier('b'), b.identifier('c')),
1326 b.spreadProperty(b.identifier('d')),
1327 ]);
1328
1329 // [foo, bar, ...baz]
1330 arrayPattern = b.arrayPattern([
1331 b.identifier('foo'),
1332 b.identifier('bar'),
1333 b.spreadElement(b.identifier('baz'))
1334 ]);
1335 });
1336
1337 it("should handle object patterns variable declarations", function() {
1338 var scope = scopeFromPattern(objectPattern);
1339
1340 assert.strictEqual(scope.declares("a"), true);
1341 assert.strictEqual(scope.declares("b"), false);
1342 assert.strictEqual(scope.declares("c"), true);
1343 assert.strictEqual(scope.declares("d"), true);
1344 });
1345
1346 it("should handle array patterns in variable declarations", function() {
1347 var scope = scopeFromPattern(arrayPattern);
1348
1349 assert.strictEqual(scope.declares("foo"), true);
1350 assert.strictEqual(scope.declares("bar"), true);
1351 assert.strictEqual(scope.declares("baz"), true);
1352 });
1353
1354 it("should handle nested patterns in variable declarations", function() {
1355 // {a, b: c, ...d, e: [foo, bar, ...baz]}
1356 objectPattern.properties.push(
1357 b.property('init', b.identifier('e'), arrayPattern)
1358 );
1359
1360 var scope = scopeFromPattern(objectPattern);
1361 assert.strictEqual(scope.declares("a"), true);
1362 assert.strictEqual(scope.declares("b"), false);
1363 assert.strictEqual(scope.declares("c"), true);
1364 assert.strictEqual(scope.declares("d"), true);
1365 assert.strictEqual(scope.declares("e"), false);
1366 assert.strictEqual(scope.declares("foo"), true);
1367 assert.strictEqual(scope.declares("bar"), true);
1368 assert.strictEqual(scope.declares("baz"), true);
1369 });
1370 });
1371
1372 // ObjectPattern with PropertyPattern and SpreadPropertyPattern
1373 // ArrayPatterhn with SpreadElementPattern
1374 describe("Mozilla Parser API", function() {
1375 var types = require('../fork')([
1376 require("../def/core"),
1377 require("../def/es6"),
1378 require("../def/es7"),
1379 require("../def/mozilla"),
1380 ]);
1381 var b = types.builders;
1382
1383 var objectPattern;
1384 var arrayPattern;
1385
1386 beforeEach(function() {
1387 // {a, b: c, ...d}
1388 objectPattern = b.objectPattern([
1389 b.propertyPattern(b.identifier('a'), b.identifier('a')),
1390 b.propertyPattern(b.identifier('b'), b.identifier('c')),
1391 b.spreadPropertyPattern(b.identifier('d')),
1392 ]);
1393
1394 // [foo, bar, ...baz]
1395 arrayPattern = b.arrayPattern([
1396 b.identifier('foo'),
1397 b.identifier('bar'),
1398 b.spreadElementPattern(b.identifier('baz'))
1399 ]);
1400 });
1401
1402 it("should handle object patterns variable declarations", function() {
1403 var scope = scopeFromPattern(objectPattern);
1404
1405 assert.strictEqual(scope.declares("a"), true);
1406 assert.strictEqual(scope.declares("b"), false);
1407 assert.strictEqual(scope.declares("c"), true);
1408 assert.strictEqual(scope.declares("d"), true);
1409 });
1410
1411 it("should handle array patterns in variable declarations", function() {
1412 var scope = scopeFromPattern(arrayPattern);
1413
1414 assert.strictEqual(scope.declares("foo"), true);
1415 assert.strictEqual(scope.declares("bar"), true);
1416 assert.strictEqual(scope.declares("baz"), true);
1417 });
1418
1419 it("should handle nested patterns in variable declarations", function() {
1420 // {a, b: c, ...d, e: [foo, bar, ...baz]}
1421 objectPattern.properties.push(
1422 b.propertyPattern(b.identifier('e'), arrayPattern)
1423 );
1424
1425 var scope = scopeFromPattern(objectPattern);
1426 assert.strictEqual(scope.declares("a"), true);
1427 assert.strictEqual(scope.declares("b"), false);
1428 assert.strictEqual(scope.declares("c"), true);
1429 assert.strictEqual(scope.declares("d"), true);
1430 assert.strictEqual(scope.declares("e"), false);
1431 assert.strictEqual(scope.declares("foo"), true);
1432 assert.strictEqual(scope.declares("bar"), true);
1433 assert.strictEqual(scope.declares("baz"), true);
1434 });
1435 });
1436 });
1437
1438 describe("types.defineMethod", function() {
1439 function at(loc) {
1440 types.namedTypes.SourceLocation.assert(loc);
1441 this.loc = loc;
1442 }
1443
1444 var thisExpr = b.thisExpression();
1445
1446 it("should allow defining an .at method", function() {
1447 assert.strictEqual(types.defineMethod("at", at), void 0);
1448 assert.strictEqual(thisExpr.loc, null);
1449
1450 thisExpr.at(b.sourceLocation(
1451 b.position(1, 0),
1452 b.position(1, 4)
1453 ));
1454
1455 assert.strictEqual(thisExpr.loc.start.line, 1);
1456 assert.strictEqual(thisExpr.loc.start.column, 0);
1457 assert.strictEqual(thisExpr.loc.end.line, 1);
1458 assert.strictEqual(thisExpr.loc.end.column, 4);
1459 });
1460
1461 it("should allow methods to be removed", function() {
1462 // Now try removing the method.
1463 assert.strictEqual(types.defineMethod("at"), at);
1464 assert.strictEqual(thisExpr.at, void 0);
1465 assert.strictEqual("at" in thisExpr, false);
1466 });
1467 });
1468
1469 describe("types.visit", function() {
1470 var objProp;
1471
1472 beforeEach(function() {
1473 objProp = b.memberExpression(
1474 b.identifier("object"),
1475 b.identifier("property"),
1476 false
1477 );
1478 });
1479
1480 it("should be identical to PathVisitor.visit", function() {
1481 assert.strictEqual(types.visit, PathVisitor.visit);
1482 });
1483
1484 it("should work with no visitors", function() {
1485 var foo = b.identifier("foo");
1486 assert.strictEqual(types.visit(foo), foo);
1487 });
1488
1489 it("should allow simple tree modifications", function() {
1490 var bar = types.visit(b.identifier("foo"), {
1491 visitIdentifier: function(path) {
1492 assert.ok(path instanceof NodePath);
1493 path.value.name = "bar";
1494 return false;
1495 }
1496 });
1497
1498 n.Identifier.assert(bar);
1499 assert.strictEqual(bar.name, "bar");
1500 });
1501
1502 it("should complain about missing this.traverse", function() {
1503 try {
1504 types.visit(objProp, {
1505 visitIdentifier: function(path) {
1506 // buh?
1507 }
1508 });
1509
1510 assert.ok(false, "should have thrown an exception");
1511
1512 } catch (err) {
1513 assert.strictEqual(
1514 err.message,
1515 "Must either call this.traverse or return false in visitIdentifier"
1516 );
1517 }
1518 });
1519
1520 it("should support this.traverse", function() {
1521 var idNames = [];
1522
1523 types.visit(objProp, {
1524 visitMemberExpression: function(path) {
1525 this.traverse(path, {
1526 visitIdentifier: function(path) {
1527 idNames.push("*" + path.value.name + "*");
1528 return false;
561529 }
1530 });
1531
1532 path.get("object", "name").replace("asdfasdf");
1533 path.get("property", "name").replace("zxcvzxcv");
1534
1535 this.visit(path.get("property"));
1536 },
1537
1538 visitIdentifier: function(path) {
1539 idNames.push(path.value.name);
1540 return false;
1541 }
1542 });
1543
1544 assert.deepEqual(idNames, ["*object*", "*property*", "zxcvzxcv"]);
1545
1546 idNames.length = 0;
1547
1548 types.visit(objProp, {
1549 visitMemberExpression: function(path) {
1550 path.get("object", "name").replace("asdfasdf");
1551 path.get("property", "name").replace("zxcvzxcv");
1552 this.traverse(path, {
1553 visitIdentifier: function(path) {
1554 idNames.push(path.value.name);
1555 return false;
1556 }
1557 });
1558 }
1559 });
1560
1561 assert.deepEqual(idNames, ["asdfasdf", "zxcvzxcv"]);
1562 });
1563
1564 it("should support this.replace", function() {
1565 var seqExpr = b.sequenceExpression([
1566 b.literal("asdf"),
1567 b.identifier("zxcv"),
1568 b.thisExpression()
1569 ]);
1570
1571 types.visit(seqExpr, {
1572 visitIdentifier: function(path) {
1573 assert.strictEqual(path.value.name, "zxcv");
1574 path.replace(
1575 b.identifier("foo"),
1576 b.identifier("bar")
571577 );
58 assert.ok(n.ImportDeclaration.check(
59 b.importDeclaration(
60 [b.importDefaultSpecifier(b.identifier("foo"))], b.literal("bar"),
61 "type")
62 )
63 );
64 assert.ok(n.ImportDeclaration.check(
65 b.importDeclaration(
66 [b.importNamespaceSpecifier(b.identifier("foo"))], b.literal("bar"))
67 )
68 );
69 });
70 });
71
72 describe("isSupertypeOf", function() {
73 it("should report correct supertype relationships", function() {
74 var def = types.Type.def;
75
76 assert.ok(def("Node").isSupertypeOf(def("Node")));
77 assert.ok(def("Node").isSupertypeOf(def("Expression")));
78 assert.ok(!def("Expression").isSupertypeOf(def("Node")));
79 assert.ok(!def("Expression").isSupertypeOf(
80 def("DebuggerStatement")));
81
82 // TODO Make this test case more exhaustive.
83 });
84 });
85
86 describe("supertype lookup", function() {
87 it("should resolve the most precise supertypes", function() {
88 var table = types.use(require("../lib/types")).computeSupertypeLookupTable({
89 Function: true,
90 Declaration: true,
91 ArrowFunctionExpression: true,
92 Expression: true,
93 Identifier: true
94 });
95
96 function check(subtype, expectedSupertype) {
97 assert.strictEqual(table[subtype], expectedSupertype);
1578 return false;
1579 }
1580 });
1581
1582 assert.strictEqual(seqExpr.expressions.length, 4);
1583
1584 var foo = seqExpr.expressions[1];
1585 n.Identifier.assert(foo);
1586 assert.strictEqual(foo.name, "foo");
1587
1588 var bar = seqExpr.expressions[2];
1589 n.Identifier.assert(bar);
1590 assert.strictEqual(bar.name, "bar");
1591
1592 types.visit(seqExpr, {
1593 visitIdentifier: function(path) {
1594 if (path.value.name === "foo") {
1595 path.replace(path.value, path.value);
981596 }
991597
100 check("FunctionExpression", "Function");
101 check("FunctionDeclaration", "Function");
102 check("VariableDeclaration", "Declaration");
103 check("Identifier", "Identifier");
104 check("ArrowFunctionExpression", "ArrowFunctionExpression");
105 check("ForInStatement");
106 check("Node");
107 check("ThisExpression", "Expression");
108 check("Property");
109 });
110
111 it("should properly linearize the inheritance hierarchy", function() {
112 assert.deepEqual(
113 types.getSupertypeNames("FunctionExpression"),
114 ["Function", "Expression", "Pattern", "Node", "Printable"]
115 );
116 });
117
118 it("should trigger an AssertionError for unknown types", function() {
119 assert.throws(function() {
120 types.getSupertypeNames("AlienBoomerangDeclaration");
121 });
122 });
123 });
124
125 describe("shallow and deep checks", function() {
126 var index = b.identifier("foo");
127 var decl = b.variableDeclaration("var", [
128 b.variableDeclarator(
129 index,
130 b.literal(42)
131 )
1598 return false;
1599 }
1600 });
1601
1602 assert.strictEqual(seqExpr.expressions.length, 5);
1603
1604 var foo = seqExpr.expressions[1];
1605 n.Identifier.assert(foo);
1606 assert.strictEqual(foo.name, "foo");
1607
1608 var foo = seqExpr.expressions[2];
1609 n.Identifier.assert(foo);
1610 assert.strictEqual(foo.name, "foo");
1611
1612 var bar = seqExpr.expressions[3];
1613 n.Identifier.assert(bar);
1614 assert.strictEqual(bar.name, "bar");
1615
1616 types.visit(seqExpr, {
1617 visitLiteral: function(path) {
1618 path.replace();
1619 return false;
1620 },
1621
1622 visitIdentifier: function(path) {
1623 if (path.value.name === "bar") {
1624 path.replace();
1625 }
1626
1627 return false;
1628 }
1629 });
1630
1631 assert.strictEqual(seqExpr.expressions.length, 3);
1632
1633 var first = seqExpr.expressions[0];
1634 n.Identifier.assert(first);
1635 assert.strictEqual(first.name, "foo");
1636
1637 var second = seqExpr.expressions[1];
1638 assert.strictEqual(second, first);
1639
1640 var third = seqExpr.expressions[2];
1641 n.ThisExpression.assert(third);
1642 });
1643
1644 it("should reuse old VisitorContext objects", function() {
1645 var objectContext;
1646 var propertyContext;
1647
1648 types.visit(objProp, {
1649 visitIdentifier: function(path) {
1650 assert.strictEqual(this.needToCallTraverse, true);
1651 this.traverse(path);
1652 assert.strictEqual(path.name, path.value.name);
1653 if (path.name === "object") {
1654 objectContext = this;
1655 } else if (path.name === "property") {
1656 propertyContext = this;
1657 }
1658 }
1659 });
1660
1661 assert.ok(objectContext);
1662 assert.ok(propertyContext);
1663 assert.strictEqual(objectContext, propertyContext);
1664 });
1665
1666 it("should dispatch to closest visitSupertype method", function() {
1667 var foo = b.identifier("foo");
1668 var bar = b.identifier("bar");
1669 var callExpr = b.callExpression(
1670 b.memberExpression(
1671 b.functionExpression(
1672 b.identifier("add"),
1673 [foo, bar],
1674 b.blockStatement([
1675 b.returnStatement(
1676 b.binaryExpression("+", foo, bar)
1677 )
1678 ])
1679 ),
1680 b.identifier("bind"),
1681 false
1682 ),
1683 [b.thisExpression()]
1684 );
1685
1686 var nodes = [];
1687 var expressions = [];
1688 var identifiers = [];
1689 var statements = [];
1690 var returnStatements = [];
1691 var functions = [];
1692
1693 function makeVisitorMethod(array) {
1694 return function(path) {
1695 array.push(path.value);
1696 this.traverse(path);
1697 };
1698 }
1699
1700 types.visit(callExpr, {
1701 visitNode: makeVisitorMethod(nodes),
1702 visitExpression: makeVisitorMethod(expressions),
1703 visitIdentifier: makeVisitorMethod(identifiers),
1704 visitStatement: makeVisitorMethod(statements),
1705 visitReturnStatement: makeVisitorMethod(returnStatements),
1706 visitFunction: makeVisitorMethod(functions)
1707 });
1708
1709 function check(array) {
1710 var rest = Array.prototype.slice.call(arguments, 1);
1711 assert.strictEqual(array.length, rest.length);
1712 for (var i = 0; i < rest.length; ++i) {
1713 assert.strictEqual(array[i], rest[i]);
1714 }
1715 }
1716
1717 check(nodes);
1718
1719 check(expressions,
1720 callExpr,
1721 callExpr.callee,
1722 callExpr.callee.object.body.body[0].argument,
1723 callExpr.arguments[0]);
1724
1725 check(identifiers,
1726 callExpr.callee.object.id,
1727 foo,
1728 bar,
1729 foo,
1730 bar,
1731 callExpr.callee.property);
1732
1733 check(statements,
1734 callExpr.callee.object.body);
1735
1736 check(returnStatements,
1737 callExpr.callee.object.body.body[0]);
1738
1739 check(functions,
1740 callExpr.callee.object);
1741 });
1742
1743 it("should replace this.currentPath with returned value", function() {
1744 assert.strictEqual(objProp.computed, false);
1745
1746 types.visit(objProp, {
1747 visitIdentifier: function(path) {
1748 if (path.value.name === "property") {
1749 path.parent.get("computed").replace(true);
1750 return b.callExpression(
1751 b.memberExpression(
1752 b.thisExpression(),
1753 b.identifier("toString"),
1754 false
1755 ),
1756 []
1757 );
1758 }
1759
1760 this.traverse(path);
1761 },
1762
1763 visitThisExpression: function(path) {
1764 return b.identifier("self");
1765 }
1766 });
1767
1768 assert.strictEqual(objProp.computed, true);
1769 n.CallExpression.assert(objProp.property);
1770
1771 var callee = objProp.property.callee;
1772 n.MemberExpression.assert(callee);
1773
1774 n.Identifier.assert(callee.object);
1775 assert.strictEqual(callee.object.name, "self");
1776
1777 n.Identifier.assert(callee.property);
1778 assert.strictEqual(callee.property.name, "toString");
1779
1780 assert.deepEqual(objProp.property.arguments, []);
1781 });
1782 });
1783
1784 describe("path.shift", function() {
1785 it("should work like Array.prototype.shift", function() {
1786 var path = new NodePath({
1787 elements: [0, "foo", true]
1788 });
1789
1790 var first = path.get("elements", 0);
1791 assert.strictEqual(first.name, 0);
1792
1793 var second = path.get("elements", 1);
1794 assert.strictEqual(second.name, 1);
1795
1796 var third = path.get("elements", 2);
1797 assert.strictEqual(third.name, 2);
1798
1799 assert.strictEqual(path.get("elements", "length").value, 3);
1800
1801 assert.strictEqual(path.get("elements").shift(), first.value);
1802 assert.strictEqual(path.get("elements", "length").value, 2);
1803 assert.strictEqual(path.get("elements", 0), second);
1804 assert.strictEqual(path.get("elements", 1), third);
1805 assert.strictEqual(second.name, 0);
1806 assert.strictEqual(third.name, 1);
1807
1808 assert.strictEqual(path.get("elements").shift(), second.value);
1809 assert.strictEqual(path.get("elements", "length").value, 1);
1810 assert.strictEqual(path.get("elements", 0), third);
1811 assert.strictEqual(third.name, 0);
1812
1813 assert.strictEqual(path.get("elements").shift(), third.value);
1814 assert.strictEqual(path.get("elements").shift(), void 0);
1815 assert.strictEqual(path.get("elements", "length").value, 0);
1816 });
1817
1818 it("should throw when path.value not an array", function() {
1819 assert.throws(function() {
1820 new NodePath({ foo: 42 }).get("foo").shift();
1821 });
1822 });
1823 });
1824
1825 describe("path.unshift", function() {
1826 it("should work like Array.prototype.unshift", function() {
1827 var path = new NodePath(b.sequenceExpression([]));
1828 var elems = path.get("expressions");
1829
1830 var one = b.literal(1);
1831 var two = b.literal(2);
1832 var three = b.literal(3);
1833 var four = b.literal(4);
1834 var five = b.literal(5);
1835
1836 assert.strictEqual(elems.get(1).parentPath, elems);
1837 assert.strictEqual(elems.get(1).node, path.value);
1838 assert.strictEqual(elems.get(1).parent, null);
1839
1840 assert.strictEqual(elems.get("length").value, 0);
1841 elems.unshift(three, four, five);
1842 assert.deepEqual(path.value.expressions, [three, four, five]);
1843 var fourPath = elems.get(1);
1844 assert.strictEqual(fourPath.value.value, 4);
1845 elems.unshift(one, two);
1846 assert.deepEqual(elems.value, [one, two, three, four, five]);
1847 elems.unshift();
1848 assert.deepEqual(elems.value, [one, two, three, four, five]);
1849 assert.strictEqual(fourPath.name, 3);
1850 assert.strictEqual(elems.get("length").value, 5);
1851
1852 assert.strictEqual(elems.get(1).parentPath, elems);
1853 assert.strictEqual(elems.get(1).node, two);
1854 assert.strictEqual(elems.get(1).parent, path);
1855 });
1856
1857 it("should throw when path.value not an array", function() {
1858 assert.throws(function() {
1859 new NodePath({ foo: 42 }).get("foo").unshift();
1860 });
1861 });
1862 });
1863
1864 describe("path.push", function() {
1865 it("should work like Array.prototype.push", function() {
1866 var path = new NodePath({ elements: [0] });
1867 var elems = path.get("elements");
1868 assert.strictEqual(elems.get("length").value, 1);
1869 elems.push(1, 2, 3);
1870 assert.deepEqual(path.value.elements, [0, 1, 2, 3]);
1871 var two = elems.get(2);
1872 assert.strictEqual(two.value, 2);
1873 elems.push(4, 5);
1874 assert.deepEqual(elems.value, [0, 1, 2, 3, 4, 5]);
1875 elems.push();
1876 assert.deepEqual(elems.value, [0, 1, 2, 3, 4, 5]);
1877 assert.strictEqual(two.name, 2);
1878 assert.strictEqual(elems.get("length").value, 6);
1879 });
1880
1881 it("should throw when path.value not an array", function() {
1882 assert.throws(function() {
1883 new NodePath({ foo: 42 }).get("foo").push("asdf");
1884 });
1885 });
1886 });
1887
1888 describe("path.pop", function() {
1889 it("should work like Array.prototype.pop", function() {
1890 var path = new NodePath({
1891 elements: [0, "foo", true]
1892 });
1893
1894 var first = path.get("elements", 0);
1895 assert.strictEqual(first.name, 0);
1896
1897 var second = path.get("elements", 1);
1898 assert.strictEqual(second.name, 1);
1899
1900 var third = path.get("elements", 2);
1901 assert.strictEqual(third.name, 2);
1902
1903 assert.strictEqual(path.get("elements", "length").value, 3);
1904
1905 assert.strictEqual(path.get("elements").pop(), third.value);
1906 assert.strictEqual(path.get("elements", "length").value, 2);
1907 assert.strictEqual(path.get("elements", 0), first);
1908 assert.strictEqual(path.get("elements", 1), second);
1909 assert.strictEqual(first.name, 0);
1910 assert.strictEqual(second.name, 1);
1911
1912 assert.strictEqual(path.get("elements").pop(), second.value);
1913 assert.strictEqual(path.get("elements", "length").value, 1);
1914 assert.strictEqual(path.get("elements", 0), first);
1915 assert.strictEqual(first.name, 0);
1916
1917 assert.strictEqual(path.get("elements").pop(), first.value);
1918 assert.strictEqual(path.get("elements").pop(), void 0);
1919 assert.strictEqual(path.get("elements", "length").value, 0);
1920 });
1921
1922 it("should throw when path.value not an array", function() {
1923 assert.throws(function() {
1924 new NodePath({ foo: 42 }).get("foo").pop();
1925 });
1926 });
1927 });
1928
1929 describe("path.insertAt", function() {
1930 it("should insert nodes at the given index", function() {
1931 var path = new NodePath({
1932 elements: [0, "foo", true]
1933 });
1934
1935 var elems = path.get("elements");
1936 elems.insertAt(1, "a", "b");
1937 assert.deepEqual(elems.value, [0, "a", "b", "foo", true]);
1938
1939 elems.insertAt(elems.get("length").value + 1, []);
1940 assert.deepEqual(elems.value, [0, "a", "b", "foo", true,, []]);
1941 assert.strictEqual(elems.get("length").value, 7);
1942
1943 elems.insertAt(elems.get("length").value + 12345);
1944 assert.deepEqual(elems.value, [0, "a", "b", "foo", true,, []]);
1945 assert.strictEqual(elems.get("length").value, 7);
1946
1947 elems.insertAt(-2, -2, -1);
1948 assert.deepEqual(elems.value, [-2, -1, 0, "a", "b", "foo", true,, []]);
1949 assert.strictEqual(elems.get("length").value, 9);
1950 });
1951
1952 it("should throw when path.value not an array", function() {
1953 assert.throws(function() {
1954 new NodePath({ foo: 42 }).get("foo").insertAt(0);
1955 });
1956 });
1957 });
1958
1959 describe("path.insertBefore", function() {
1960 it("should insert nodes before the current path", function() {
1961 var zero = b.literal(0);
1962 var one = b.literal(1);
1963 var two = b.literal(2);
1964 var foo = b.literal("foo");
1965 var truth = b.literal(true);
1966
1967 var path = new NodePath(b.sequenceExpression([zero, foo, truth]));
1968 var fooPath = path.get("expressions", 1);
1969 var truePath = path.get("expressions", 2);
1970 fooPath.insertBefore(one, two);
1971 assert.deepEqual(
1972 fooPath.parent.node.expressions,
1973 [zero, one, two, foo, truth]
1974 );
1975
1976 assert.strictEqual(path.get("expressions", 3), fooPath);
1977 assert.strictEqual(fooPath.value.value, "foo");
1978
1979 assert.strictEqual(path.get("expressions", 4), truePath);
1980 assert.strictEqual(truePath.value.value, true);
1981 });
1982
1983 it("should throw when path.parentPath.value not an array", function() {
1984 assert.throws(function() {
1985 new NodePath({ foo: 42 }).get("foo").insertBefore(0);
1986 });
1987 });
1988 });
1989
1990 describe("path.insertAfter", function() {
1991 it("should insert nodes after the current path", function() {
1992 var zero = b.literal(0);
1993 var one = b.literal(1);
1994 var two = b.literal(2);
1995 var foo = b.literal("foo");
1996 var truth = b.literal(true);
1997
1998 var path = new NodePath(b.sequenceExpression([zero, foo, truth]));
1999 var fooPath = path.get("expressions", 1);
2000 var truePath = path.get("expressions", 2);
2001 fooPath.insertAfter(one, two);
2002 assert.deepEqual(
2003 fooPath.parent.node.expressions,
2004 [zero, foo, one, two, truth]
2005 );
2006
2007 assert.strictEqual(path.get("expressions", 1), fooPath);
2008 assert.strictEqual(fooPath.value.value, "foo");
2009
2010 assert.strictEqual(path.get("expressions", 2).value.value, 1);
2011 assert.strictEqual(path.get("expressions", 3).value.value, 2);
2012
2013 assert.strictEqual(path.get("expressions", 4), truePath);
2014 assert.strictEqual(truePath.value.value, true);
2015
2016 var three = b.literal(3)
2017 truePath.insertAfter(three);
2018 assert.deepEqual(
2019 fooPath.parent.node.expressions,
2020 [zero, foo, one, two, truth, three]
2021 );
2022 });
2023
2024 it("should throw when path.parentPath.value not an array", function() {
2025 assert.throws(function() {
2026 new NodePath({ foo: 42 }).get("foo").insertAfter(0);
2027 });
2028 });
2029 });
2030
2031 describe("types.astNodesAreEquivalent", function() {
2032 it("should work for simple values", function() {
2033 types.astNodesAreEquivalent.assert(1, 2 - 1);
2034 types.astNodesAreEquivalent.assert("1", 1);
2035 types.astNodesAreEquivalent.assert(true, !false);
2036
2037 var d1 = new Date;
2038 var d2 = new Date(+d1);
2039 assert.notStrictEqual(d1, d2);
2040 types.astNodesAreEquivalent.assert(d1, d2);
2041
2042 types.astNodesAreEquivalent.assert(/x/, /x/);
2043 assert.strictEqual(types.astNodesAreEquivalent(/x/g, /x/), false);
2044 });
2045
2046 it("should work for arrays", function() {
2047 types.astNodesAreEquivalent.assert([], [1, 2, 3].slice(10));
2048 types.astNodesAreEquivalent.assert([1, 2, 3], [1].concat(2, [3]));
2049 types.astNodesAreEquivalent.assert([1,, 3], [1,, 3,]);
2050 assert.strictEqual(
2051 types.astNodesAreEquivalent([1,, 3], [1, void 0, 3]),
2052 false
2053 );
2054 });
2055
2056 it("should work for objects", function() {
2057 types.astNodesAreEquivalent.assert({
2058 foo: 42,
2059 bar: "asdf"
2060 }, {
2061 bar: "asdf",
2062 foo: 42
2063 });
2064
2065 assert.strictEqual(types.astNodesAreEquivalent({
2066 foo: 42,
2067 bar: "asdf",
2068 baz: true
2069 }, {
2070 bar: "asdf",
2071 foo: 42
2072 }), false);
2073
2074 assert.strictEqual(types.astNodesAreEquivalent({
2075 foo: 42,
2076 bar: "asdf"
2077 }, {
2078 bar: "asdf",
2079 foo: 42,
2080 baz: true
2081 }), false);
2082 });
2083
2084 it("should work for AST nodes", function() {
2085 function check(src1, src2) {
2086 types.astNodesAreEquivalent.assert(parse(src1), parse(src2));
2087 }
2088
2089 function checkNot(src1, src2) {
2090 var ast1 = parse(src1, { loc: true, range: true });
2091 var ast2 = parse(src2, { loc: true });
2092
2093 assert.throws(function() {
2094 types.astNodesAreEquivalent.assert(ast1, ast2);
2095 });
2096
2097 var problemPath = [];
2098 types.astNodesAreEquivalent(parse(src1), parse(src2), problemPath);
2099 assert.notStrictEqual(problemPath.length, 0);
2100
2101 var a = ast1;
2102 var b = ast2;
2103
2104 problemPath.forEach(function(name) {
2105 assert.strictEqual(name in a, true);
2106 assert.strictEqual(name in b, true);
2107 a = a[name];
2108 b = b[name];
2109 });
2110
2111 assert.notStrictEqual(a, b);
2112 }
2113
2114 check("1\n;", "1;");
2115
2116 check("console.log(this.toString(36));", [
2117 "// leading comment",
2118 "console.log(",
2119 " this.toString(36)",
2120 "/* trailing comment */)"
2121 ].join("\n"));
2122
2123 check("foo()", "foo /*anonymous*/ ()");
2124
2125 check("new (bar(1,2)(3,4)).baz.call(null)",
2126 "new( bar( 1,2) \n (3,4)). baz.call( null)");
2127
2128 check([
2129 "(function(x) {",
2130 " Foo = /asdf/.test(x);",
2131 "}());"
2132 ].join("\n"), [
2133 "(function(x) {",
2134 " Foo = /asdf/.test(x);",
2135 "})();"
2136 ].join("\n\n"));
2137
2138 checkNot([
2139 "(function(x) {",
2140 " Foo = /asdf/.test(x);",
2141 "}());"
2142 ].join("\n"), [
2143 "(function(x) {",
2144 " Foo = /asdf/.test(x);",
2145 "})('~asdf~');"
2146 ].join("\n\n"));
2147
2148 checkNot([
2149 "(function(x) {",
2150 " var Foo = /asdf/.test(x);",
2151 "}());"
2152 ].join("\n"), [
2153 "(function(x) {",
2154 " Foo = /asdf/.test(x);",
2155 "})(/*'~asdf~'*/);"
2156 ].join("\n\n"));
2157 });
2158 });
2159
2160 describe("RegExpLiteral nodes", function() {
2161 it("should have a default-computable .regex field", function() {
2162 var ast = parse('/x*/gmi.test("xxx")');
2163 var regExp = ast.body[0].expression.callee.object;
2164
2165 n.Literal.assert(regExp);
2166 isRegExp.assert(regExp.value);
2167
2168 var regex = types.getFieldValue(regExp, "regex");
2169
2170 regex.flags = regex.flags.split("").sort().join("");
2171
2172 assert.deepEqual(regex, {
2173 pattern: "x*",
2174 flags: "gim"
2175 });
2176
2177 types.Type.fromObject({
2178 pattern: isString,
2179 flags: isString
2180 }).assert(regex);
2181 });
2182
2183 it("should typecheck with explicit .regex field", function() {
2184 var stringLiteral = b.literal("asdf");
2185 assert.strictEqual(stringLiteral.regex, null);
2186 n.Literal.assert(stringLiteral, true);
2187
2188 var regExpLiteral = b.literal(/a.b/gi);
2189 assert.strictEqual(regExpLiteral.regex.pattern, "a.b");
2190 assert.strictEqual(regExpLiteral.regex.flags, "ig");
2191 n.Literal.assert(regExpLiteral, true);
2192
2193 regExpLiteral.regex.pattern = 1234;
2194 assert.strictEqual(n.Literal.check(regExpLiteral, true), false);
2195 });
2196 });
2197
2198 describe("BigIntLiteral nodes", function () {
2199 it("should parse correctly with Babylon", function () {
2200 var types = require('../fork')([
2201 require("../def/babel"),
1322202 ]);
133
134 it("should work when shallow", function() {
135 assert.ok(n.Node.check(decl));
136 assert.ok(n.Statement.check(decl));
137 assert.ok(n.Declaration.check(decl));
138 assert.ok(n.VariableDeclaration.check(decl));
139 });
140
141 it("should work when deep", function() {
142 assert.ok(n.Node.check(decl, true));
143 assert.ok(n.Statement.check(decl, true));
144 assert.ok(n.Declaration.check(decl, true));
145 assert.ok(n.VariableDeclaration.check(decl, true));
146 });
147
148 it("should fail when expected", function() {
149 // Not an Expression.
150 assert.ok(!n.Expression.check(decl));
151
152 // This makes decl cease to conform to n.VariableDeclaration.
153 decl.declarations.push(b.literal("bar"));
154
155 assert.ok(n.Node.check(decl));
156 assert.ok(n.Statement.check(decl));
157 assert.ok(n.Declaration.check(decl));
158 assert.ok(n.VariableDeclaration.check(decl));
159
160 assert.ok(!n.Node.check(decl, true));
161 assert.ok(!n.Statement.check(decl, true));
162 assert.ok(!n.Declaration.check(decl, true));
163
164 // As foretold above.
165 assert.ok(!n.VariableDeclaration.check(decl, true));
166
167 // Still not an Expression.
168 assert.ok(!n.Expression.check(decl));
169 });
170
171 var fs = b.forStatement(
172 decl,
173 b.binaryExpression("<", index, b.literal(48)),
174 b.updateExpression("++", index, true),
175 b.blockStatement([
176 b.expressionStatement(
177 b.callExpression(index, [])
178 )
179 ])
180 );
181
182 it("should disagree according to depth", function() {
183 assert.ok(n.Node.check(fs));
184 assert.ok(n.Statement.check(fs));
185 assert.ok(n.ForStatement.check(fs));
186
187 // Not a true ForStatement because fs.init is not a true
188 // VariableDeclaration.
189 assert.ok(!n.Node.check(fs, true));
190 assert.ok(!n.Statement.check(fs, true));
191 assert.ok(!n.ForStatement.check(fs, true));
192 });
193 });
194
195 function validateProgram(file) {
196 var fullPath = path.join(__dirname, "..", file);
197
198 it("should validate " + file + " with Esprima", function(done) {
199 var parse = require("esprima").parse;
200
201 fs.readFile(fullPath, "utf8", function(err, code) {
202 if (err) throw err;
203
204 n.Program.assert(parse(code), true);
205 n.Program.assert(parse(code, { loc: true }), true);
206
207 done();
208 });
209 });
210
211 it("should validate " + file + " with Babel", function(done) {
212 fs.readFile(fullPath, "utf8", function(err, code) {
213 if (err) throw err;
214 var ast = babylonParse(code);
215 n.Program.assert(ast, true);
216 done();
217 });
218 });
219 }
220
221 describe("whole-program validation", function() {
222 this.timeout(20000);
223
224 validateProgram("main.js");
225 validateProgram("lib/shared.js");
226 validateProgram("def/core.js");
227 validateProgram("lib/types.js");
228 validateProgram("test/run.js");
229 validateProgram("test/data/backbone.js");
230 validateProgram("test/data/jquery-1.9.1.js");
231 });
232
233 describe("esprima Syntax types", function() {
234 var def = types.Type.def;
235 var typeNames = {};
236
237 function addTypeName(name) {
238 typeNames[name] = name;
2203 var n = types.namedTypes;
2204 var BigIntLiteral = n.BigIntLiteral;
2205 var parse = require("babylon").parse;
2206 var parseOptions = {
2207 plugins: ["bigInt"]
2208 };
2209
2210 function check(code) {
2211 parseAndCheck(code);
2212 parseAndCheck("-" + code);
2213 parseAndCheck("+" + code);
2392214 }
2402215
241 Object.keys(require("esprima").Syntax).forEach(addTypeName);
242 Object.keys(require("esprima-fb").Syntax).forEach(addTypeName);
243 Object.keys(
244 require("babel-types").VISITOR_KEYS
245 ).forEach(addTypeName);
246
247 it("should all be buildable", function() {
248 Object.keys(typeNames).forEach(function(name) {
249 assert.ok(hasOwn.call(n, name), name);
250 assert.strictEqual(def(name).buildable, true, name);
251 });
252 });
253
254 it("builders for subtypes of Expression should have equivalent ExpressionStatement builders", function() {
255 Object.keys(typeNames).forEach(function(name) {
256 if (def(name).buildable &&
257 def("Expression").isSupertypeOf(def(name))) {
258 var statementBuilderName = rawTypes.getStatementBuilderName(name);
259 assert.ok(b[statementBuilderName], name + ":" +statementBuilderName);
260 }
261 });
262
263 // sanity check
264 var expStmt = b.assignmentStatement("=", b.identifier("a"), b.identifier("b"));
265 assert.strictEqual(expStmt.type, "ExpressionStatement");
266 });
267 });
268
269 describe("types.getFieldValue", function() {
270 it("should work for explicit fields", function() {
271 assert.strictEqual(
272 types.getFieldValue({
273 type: "CatchClause"
274 }, "type"),
275 "CatchClause"
276 );
277
278 assert.strictEqual(
279 types.getFieldValue({
280 type: "CatchClause",
281 guard: b.identifier("test")
282 }, "guard").name,
283 "test"
284 );
285 });
286
287 it("should work for implicit/default fields", function() {
288 assert.strictEqual(
289 types.getFieldValue({
290 type: "CatchClause"
291 }, "guard"),
292 null
293 );
294
295 assert.strictEqual(
296 types.getFieldValue({
297 type: "CatchClause"
298 }, "asdf"),
299 void 0
300 );
301
302 assert.deepEqual(
303 types.getFieldValue({
304 type: "TryStatement",
305 }, "handler"),
306 null
307 );
308
309 assert.deepEqual(
310 types.getFieldValue({
311 type: "TryStatement",
312 }, "handlers"),
313 []
314 );
315
316 assert.deepEqual(
317 types.getFieldValue({
318 type: "TryStatement",
319 }, "guardedHandlers"),
320 []
321 );
322 });
323
324 it("should work for explicitly undefined fields", function() {
325 assert.deepEqual(
326 types.getFieldValue({
327 type: "TryStatement",
328 guardedHandlers: void 0
329 }, "guardedHandlers"),
330 []
331 );
332 });
333
334 it("should handle undefined objects", function() {
335 assert.equal(
336 types.getFieldValue(undefined, "name"),
337 undefined
338 );
339 });
340 });
341
342 describe("types.eachField", function() {
343 var context = {};
344
345 function check(node, names) {
346 var seen = [];
347
348 types.eachField(node, function(name, value) {
349 assert.strictEqual(this, context);
350 if (name === "type")
351 assert.strictEqual(node.type, value);
352 seen.push(name);
353 }, context);
354
355 assert.deepEqual(seen.sort(), names.sort());
2216 function parseAndCheck(code) {
2217 var file = parse(code, parseOptions);
2218 var exp = file.program.body[0].expression;
2219 if (n.UnaryExpression.check(exp)) {
2220 checkExp(exp.argument);
2221 } else {
2222 checkExp(exp);
2223 }
3562224 }
3572225
358 it("should give correct keys for supertypes", function() {
359 check({ type: "Expression" }, ["type"]);
360 });
361
362 it("should work for non-buildable types", function() {
363 check({ type: "Position" }, [
364 "type", "line", "column"
365 ]);
366
367 check({ type: "SourceLocation" }, [
368 "type", "start", "end", "source"
369 ]);
370 });
371
372 it("should respect hidden fields", function() {
373 check({ type: "TryStatement" }, [
374 // Note that the "handlers" field is now hidden from eachField.
375 "type", "block", "handler", "guardedHandlers", "finalizer"
376 ]);
377 });
378
379 check({ type: "CatchClause" }, [
380 "type", "param", "guard", "body"
381 ]);
382
383 it("should complain about invalid types", function() {
384 assert.throws(function() {
385 check({ type: "asdf" }, ["type"]);
386 }, "did not recognize object of type " + JSON.stringify("asdf"));
387 });
388
389 it("should infer SourceLocation types", function() {
390 check({
391 line: 10,
392 column: 37
393 }, ["line", "column"]);
394 });
395 });
396
397 describe("types.visit", function() {
398 var call = b.expressionStatement(
399 b.callExpression(
400 b.memberExpression(
401 b.identifier("foo"),
402 b.identifier("bar"),
403 false
404 ),
405 [b.literal("baz")]
406 )
407 );
408
409 var ts = b.tryStatement(
410 b.blockStatement([call, call]),
411 b.catchClause(
412 b.identifier("err"),
413 null,
414 b.blockStatement([])
415 )
416 );
417
418 it("should have correct .parent path", function() {
419 var literalCount = 0;
420
421 n.TryStatement.assert(types.visit(ts, {
422 visitLiteral: function(path) {
423 var node = path.node;
424 literalCount += 1;
425 assert.strictEqual(node.value, "baz");
426 assert.strictEqual(path.parent.node, call.expression);
427 assert.strictEqual(path.parent.parent.node, call);
428 assert.strictEqual(path.parent.parent.parent.node, ts.block);
429 assert.strictEqual(path.parent.parent.parent.parent.node, ts);
430 assert.strictEqual(path.parent.parent.parent.parent.parent, null);
431 this.traverse(path);
432 }
433 }), true);
434
435 assert.strictEqual(literalCount, 2);
436 });
437
438 it("should abort subtree traversal when false returned", function() {
439 var ids = {};
440
441 types.visit(ts, {
442 visitMemberExpression: function(path) {
443 return false;
444 },
445
446 visitIdentifier: function(path) {
447 ids[path.node.name] = true;
448 this.traverse(path);
449 }
450 });
451
452 // Make sure all identifers beneath member expressions were skipped.
453 assert.deepEqual(ids, { err: true });
454
455 ids = {};
456
457 types.visit(ts, {
458 visitIdentifier: function(path) {
459 ids[path.node.name] = true;
460 this.traverse(path);
461 }
462 });
463
464 // Now make sure those identifiers (foo and bar) were visited.
465 assert.deepEqual(ids, {
466 err: true,
467 foo: true,
468 bar: true
469 });
470 });
471
472 it("this.abort() should abort entire traversal", function() {
473 var literal = "not visited";
474 var unvisitedTypes = [];
475 var root = types.visit(call, {
476 visitIdentifier: function(path) {
477 if (path.value.name === "foo") {
478 this.abort();
479 }
480 },
481
482 visitLiteral: function(path) {
483 literal = path.value;
484 this.traverse(path);
485 },
486
487 visitNode: function(path) {
488 unvisitedTypes.push(path.value.type);
489 this.traverse(path);
490 }
491 });
492
493 assert.strictEqual(root, call);
494 assert.strictEqual(literal, "not visited");
495 assert.deepEqual(unvisitedTypes, [
496 "ExpressionStatement",
497 "CallExpression",
498 "MemberExpression"
499 ]);
500 });
501
502 it("this.abort() should be cancelable", function() {
503 var literal = "not visited";
504 var unvisitedTypes = [];
505 var root = types.visit(call, {
506 visitIdentifier: function(path) {
507 if (path.value.name === "foo") {
508 this.abort();
509 }
510 },
511
512 visitMemberExpression: function(path) {
513 try {
514 this.traverse(path);
515 } catch (err) {
516 assert.ok(err instanceof this.AbortRequest);
517 err.cancel();
518 }
519 },
520
521 visitLiteral: function(path) {
522 literal = path.value;
523 this.traverse(path);
524 },
525
526 visitNode: function(path) {
527 unvisitedTypes.push(path.value.type);
528 this.traverse(path);
529 }
530 });
531
532 assert.strictEqual(root, call);
533
534 n.Literal.assert(literal);
535 assert.strictEqual(literal.value, "baz");
536 assert.strictEqual(literal, call.expression.arguments[0]);
537
538 assert.deepEqual(unvisitedTypes, [
539 "ExpressionStatement",
540 "CallExpression"
541 // Note that the MemberExpression and the Literal were visited
542 // by their type-specific methods, so they were not visited by
543 // the catch-all visitNode method.
544 ]);
545 });
546
547 it("should visit comments", function() {
548 var ast = parse([
549 "function getArgs(/*arguments*/) {",
550 " // Turn arguments into an array.",
551 " return Array.prototype.slice.call(arguments);",
552 "}"
553 ].join("\n"), {
554 comment: true
555 });
556
557 var blockComments = [];
558 var lineComments = [];
559
560 types.visit(ast, {
561 visitComment: function(path) {
562 this.traverse(path);
563 if (n.Block.check(path.value)) {
564 blockComments.push(path.value);
565 } else if (n.Line.check(path.value)) {
566 lineComments.push(path.value);
567 }
568 }
569 });
570
571 assert.strictEqual(blockComments.length, 1);
572 assert.strictEqual(blockComments[0].value, "arguments");
573
574 assert.strictEqual(lineComments.length, 1);
575 assert.strictEqual(
576 lineComments[0].value,
577 " Turn arguments into an array."
578 );
579
580 blockComments.length = 0;
581 lineComments.length = 0;
582
583 types.visit(ast, {
584 visitBlock: function(path) {
585 blockComments.push(path.value);
586 this.traverse(path);
587 }
588 });
589
590 assert.strictEqual(blockComments.length, 1);
591 assert.strictEqual(blockComments[0].value, "arguments");
592
593 assert.strictEqual(lineComments.length, 0);
594
595 blockComments.length = 0;
596 lineComments.length = 0;
597
598 types.visit(ast, {
599 visitLine: function(path) {
600 lineComments.push(path.value);
601 this.traverse(path);
602 }
603 });
604
605 assert.strictEqual(blockComments.length, 0);
606
607 assert.strictEqual(lineComments.length, 1);
608 assert.strictEqual(
609 lineComments[0].value,
610 " Turn arguments into an array."
611 );
612
613 blockComments.length = 0;
614 lineComments.length = 0;
615
616 types.visit(ast, {
617 visitBlock: function(path) {
618 blockComments.push(path.value);
619 this.traverse(path);
620 },
621
622 visitLine: function(path) {
623 lineComments.push(path.value);
624 this.traverse(path);
625 }
626 });
627
628 assert.strictEqual(blockComments.length, 1);
629 assert.strictEqual(blockComments[0].value, "arguments");
630
631 assert.strictEqual(lineComments.length, 1);
632 assert.strictEqual(
633 lineComments[0].value,
634 " Turn arguments into an array."
635 );
636 });
637 });
638
639 describe("path traversal", function() {
640 var call = b.expressionStatement(
641 b.callExpression(
642 b.memberExpression(
643 b.identifier("foo"),
644 b.identifier("bar"),
645 false
646 ),
647 [b.literal("baz")]
648 )
649 );
650
651 it("should accept root paths as well as AST nodes", function() {
652 var path = new NodePath(call).get("expression", "callee");
653 var idCount = 0;
654
655 // Note that we're passing a path instead of a node as the first
656 // argument to types.traverse.
657 types.visit(path, {
658 visitIdentifier: function(path) {
659 var node = path.node;
660 ++idCount;
661
662 if (node.name === "bar") {
663 n.MemberExpression.assert(path.parent.node);
664 n.CallExpression.assert(path.parent.parent.node);
665 n.ExpressionStatement.assert(path.parent.parent.parent.node);
666 }
667
668 this.traverse(path);
669 }
670 });
671
672 assert.strictEqual(idCount, 2);
673 });
674 });
675
676 describe("replacing the root", function() {
677 var ast = b.expressionStatement(
678 b.unaryExpression("!", b.sequenceExpression([
679 b.identifier("a"),
680 b.identifier("b"),
681 b.identifier("c")
682 ]))
683 );
684
685 it("should be possible", function() {
686 var callExp = types.visit(ast, {
687 visitExpressionStatement: function(path) {
688 path.replace(b.callExpression(b.identifier("f"), [
689 path.node.expression
690 ]));
691
692 this.traverse(path);
693 }
694 });
695
696 n.CallExpression.assert(callExp, true);
697 });
698 });
699
700 describe("NodePath", function() {
701 it("should have the expected type hierarchy", function() {
702 assert.strictEqual(new Path({}).constructor, Path);
703
704 var np = new NodePath(b.identifier("foo"));
705 assert.strictEqual(np.constructor, NodePath);
706 assert.ok(np.get("name") instanceof NodePath);
707 });
708
709 var ast = b.expressionStatement(
710 b.unaryExpression("!", b.sequenceExpression([
711 b.identifier("a"),
712 b.identifier("b"),
713 b.identifier("c")
714 ]))
715 );
716
717 var path = new NodePath(ast);
718
719 it("should have sane values, nodes, parents", function() {
720 var opPath = path.get("expression", "operator");
721 assert.strictEqual(opPath.value, "!");
722 assert.strictEqual(opPath.node, ast.expression);
723 assert.strictEqual(opPath.parent, path);
724 assert.strictEqual(opPath.parent.node, ast);
725 });
726
727 var binaryYield = b.expressionStatement(
728 b.logicalExpression(
729 "&&",
730 b.yieldExpression(b.identifier("a"), false),
731 b.yieldExpression(b.identifier("b"), true)
732 )
733 );
734
735 it("should support .needsParens()", function() {
736 var argPath = path.get("expression", "argument");
737 assert.ok(argPath.needsParens());
738
739 var exprsPath = argPath.get("expressions");
740 assert.ok(!exprsPath.needsParens());
741 assert.strictEqual(exprsPath.get("length").value, 3);
742 assert.ok(!exprsPath.get(1).needsParens());
743
744 var byPath = new NodePath(binaryYield);
745 assert.ok(!byPath.get("expression").needsParens());
746 assert.ok(byPath.get("expression", "left").needsParens());
747 assert.ok(byPath.get("expression", "right").needsParens());
748
749 var sequenceAssignmentAST = b.assignmentExpression(
750 '=',
751 b.identifier('a'),
752 b.sequenceExpression([b.literal(1), b.literal(2)])
753 );
754
755 var sequenceAssignmentPath = new NodePath(sequenceAssignmentAST);
756 assert.ok(sequenceAssignmentPath.get("right").needsParens());
757 });
758
759 it("should support .needsParens(true)", function() {
760 var programPath = new NodePath(parse("(function(){})"));
761 var funExpPath = programPath.get("body", 0, "expression");
762 n.FunctionExpression.assert(funExpPath.value);
763 assert.strictEqual(funExpPath.needsParens(), true);
764 assert.strictEqual(funExpPath.canBeFirstInStatement(), false);
765 assert.strictEqual(funExpPath.firstInStatement(), true);
766 assert.strictEqual(funExpPath.needsParens(true), false);
767
768 programPath = new NodePath(parse("({ foo: 42 })"));
769 var objLitPath = programPath.get("body", 0, "expression");
770 n.ObjectExpression.assert(objLitPath.value);
771 assert.strictEqual(objLitPath.needsParens(), true);
772 assert.strictEqual(objLitPath.canBeFirstInStatement(), false);
773 assert.strictEqual(objLitPath.firstInStatement(), true);
774 assert.strictEqual(objLitPath.needsParens(true), false);
775 });
776
777 it("should prune redundant variable declaration nodes", function() {
778 var programPath = new NodePath(parse("(function(){var y = 1,x = 2;})"));
779 var funBlockStatementPath = programPath.get("body", 0, "expression", "body");
780 var variableDeclaration = funBlockStatementPath.get("body", 0);
781 var yVariableDeclaratorPath = variableDeclaration.get("declarations", 0);
782 var xVariableDeclaratorPath = variableDeclaration.get("declarations", 1);
783
784 n.VariableDeclarator.assert(yVariableDeclaratorPath.node);
785 n.VariableDeclarator.assert(xVariableDeclaratorPath.node);
786
787 var remainingNodePath = yVariableDeclaratorPath.prune();
788
789 assert.strictEqual(remainingNodePath, variableDeclaration);
790
791 remainingNodePath = xVariableDeclaratorPath.prune();
792
793 assert.strictEqual(remainingNodePath, funBlockStatementPath);
794 assert.strictEqual(funBlockStatementPath.get("body", 0).value, undefined);
795 });
796
797 it("should prune redundant expression statement nodes", function() {
798 var programPath = new NodePath(parse("(function(){key = 'value';})"));
799 var funBlockStatementPath = programPath.get("body", 0, "expression", "body");
800 var assignmentExpressionPath = funBlockStatementPath.get("body", 0, "expression");
801
802 n.AssignmentExpression.assert(assignmentExpressionPath.node);
803
804 var remainingNodePath = assignmentExpressionPath.prune();
805
806 assert.strictEqual(remainingNodePath, funBlockStatementPath);
807 assert.strictEqual(funBlockStatementPath.value.body.length, 0);
808 });
809
810 it("should prune redundant if statement node if no consequent and alternate remain after prune", function() {
811 var programPath = new NodePath(parse("if(true){var t = 0;}"));
812 var consequentNodePath = programPath.get("body", 0, "consequent");
813
814 n.BlockStatement.assert(consequentNodePath.node);
815
816 var remainingNodePath = consequentNodePath.prune();
817
818 var testExpressionNodePath = programPath.get("body", 0);
819
820 n.ExpressionStatement.assert(remainingNodePath.node);
821 assert.strictEqual(remainingNodePath, testExpressionNodePath);
822 });
823
824 it("should modify if statement node if consequent is pruned and alternate remains", function() {
825 var programPath = new NodePath(parse("if(x > 10){var t = 0;}else{var f = 2;}"));
826 var consequentNodePath = programPath.get("body", 0, "consequent");
827
828 n.BlockStatement.assert(consequentNodePath.node);
829
830 var remainingNodePath = consequentNodePath.prune();
831
832 var modifiedIfStatementNodePath = programPath.get("body", 0);
833 var negatedTestExpression = modifiedIfStatementNodePath.get("test");
834
835 n.IfStatement.assert(remainingNodePath.node);
836 n.UnaryExpression.assert(negatedTestExpression.node);
837 assert.strictEqual(remainingNodePath, modifiedIfStatementNodePath);
838 assert.strictEqual(negatedTestExpression.node.operator, "!");
839 });
840
841 it("should modify if statement node if consequent is pruned, alternate remains with no double negation", function() {
842 var programPath = new NodePath(parse("if(!condition){var t = 0;}else{var f = 2;}"));
843 var consequentNodePath = programPath.get("body", 0, "consequent");
844
845 n.BlockStatement.assert(consequentNodePath.node);
846
847 var remainingNodePath = consequentNodePath.prune();
848
849 var modifiedIfStatementNodePath = programPath.get("body", 0);
850 var testExpression = modifiedIfStatementNodePath.get("test");
851
852 n.IfStatement.assert(remainingNodePath.node);
853 n.Identifier.assert(testExpression.node);
854 assert.strictEqual(remainingNodePath, modifiedIfStatementNodePath);
855 });
856 });
857
858 describe("path.replace", function() {
859 var ast;
860
861 beforeEach(function() {
862 ast = b.functionDeclaration(
863 b.identifier("fn"),
864 [],
865 b.blockStatement([
866 b.variableDeclaration(
867 "var",
868 [b.variableDeclarator(b.identifier("a"), null)]
869 )
870 ])
871 );
872 });
873
874 it("should support replacement with a single node", function() {
875 types.visit(ast, {
876 visitIdentifier: function(path) {
877 if (path.node.name === "a") {
878 path.replace(b.identifier("b"));
879 }
880 this.traverse(path);
881 }
882 });
883
884 assert.equal(ast.body.body[0].declarations[0].id.name, "b");
885 });
886
887 it("should support replacement in an array with a single node", function() {
888 types.visit(ast, {
889 visitVariableDeclaration: function(path) {
890 path.replace(b.returnStatement(null));
891 this.traverse(path);
892 }
893 });
894
895 assert.equal(ast.body.body.length, 1);
896 assert.ok(n.ReturnStatement.check(ast.body.body[0]));
897 });
898
899 it("should support replacement with nothing", function() {
900 types.visit(ast, {
901 visitVariableDeclaration: function(path) {
902 path.replace();
903 this.traverse(path);
904 }
905 });
906
907 assert.equal(ast.body.body.length, 0);
908 });
909
910 it("should support replacement with itself plus more in an array", function() {
911 types.visit(ast, {
912 visitVariableDeclaration: function(path) {
913 var scopeBody = path.scope.path.get("body", "body");
914
915 // This is contrived such that we just happen to be replacing
916 // the same node we're currently processing, perhaps using a
917 // helper function to create variables at the top of the scope.
918 assert.strictEqual(scopeBody.get(0), path);
919
920 // Prepend `var $$;` inside the block. This should update our
921 // `this` NodePath to correct its array index so that a
922 // subsequent replace will still work.
923 scopeBody.get(0).replace(
924 b.variableDeclaration(
925 "var",
926 [b.variableDeclarator(b.identifier("$$"), null)]
927 ),
928 scopeBody.get(0).value
929 );
930
931 // Now do it again to make sure all the other indexes are
932 // updated, too.
933 scopeBody.get(0).replace(
934 b.variableDeclaration(
935 "var",
936 [b.variableDeclarator(b.identifier("$2"), null)]
937 ),
938 scopeBody.get(0).value
939 );
940
941 assert.strictEqual(scopeBody.get(0), path);
942
943 // Then replace the node, not the one we just added.
944 return b.returnStatement(b.identifier("$3"));
945 }
946 });
947
948 var statements = ast.body.body;
949 assert.deepEqual(
950 statements.map(function(node) { return node.type; }),
951 ['ReturnStatement', 'VariableDeclaration', 'VariableDeclaration']
952 );
953
954 n.ReturnStatement.assert(statements[0]);
955 assert.equal(statements[0].argument.name, "$3");
956
957 n.VariableDeclaration.assert(statements[1]);
958 assert.equal(statements[1].declarations[0].id.name, "$$");
959
960 n.VariableDeclaration.assert(statements[2]);
961 assert.equal(statements[2].declarations[0].id.name, "a");
962 });
963
964 it("should not throw when replacing the same node twice", function() {
965 types.visit(ast, {
966 visitVariableDeclaration: function(path) {
967 path.replace(b.expressionStatement(b.literal(null)));
968 n.ExpressionStatement.assert(path.value);
969 n.Literal.assert(path.value.expression);
970 assert.strictEqual(path.value.expression.value, null);
971
972 path.replace(b.expressionStatement(b.literal("OK")));
973 n.ExpressionStatement.assert(path.value);
974 n.Literal.assert(path.value.expression);
975 assert.strictEqual(path.value.expression.value, "OK");
976
977 if (path.parentPath.get(path.name) !== path) {
978 assert.ok(false, "Should have reused the same path");
979 }
980
981 this.traverse(path);
982 }
983 });
984 });
985 });
986
987 describe("global scope", function() {
988 var scope = [
989 "var foo = 42;",
990 "function bar(baz) {",
991 " return baz + foo;",
992 "}"
993 ];
994
995 var ast = parse(scope.join("\n"));
996
997 it("should be reachable from nested scopes", function() {
998 var globalScope;
999
1000 types.visit(ast, {
1001 visitProgram: function(path) {
1002 assert.strictEqual(path.scope.isGlobal, true);
1003 globalScope = path.scope;
1004 this.traverse(path);
1005 },
1006
1007 visitFunctionDeclaration: function(path) {
1008 var node = path.node;
1009 assert.strictEqual(path.scope.isGlobal, false);
1010
1011 assert.strictEqual(node.id.name, "bar");
1012 assert.notStrictEqual(path.scope, globalScope);
1013 assert.strictEqual(path.scope.isGlobal, false);
1014 assert.strictEqual(path.scope.parent, globalScope);
1015
1016 assert.strictEqual(path.scope.getGlobalScope(), globalScope);
1017
1018 this.traverse(path);
1019 }
1020 });
1021 });
1022
1023 it("should be found by .lookup and .declares", function() {
1024 var globalScope;
1025
1026 types.visit(ast, {
1027 visitProgram: function(path) {
1028 assert.strictEqual(path.scope.isGlobal, true);
1029 globalScope = path.scope;
1030 this.traverse(path);
1031 },
1032
1033 visitFunctionDeclaration: function(path) {
1034 assert.ok(globalScope.declares("foo"));
1035 assert.ok(globalScope.declares("bar"));
1036 assert.strictEqual(path.scope.lookup("foo"), globalScope);
1037 assert.strictEqual(path.scope.lookup("bar"), globalScope);
1038
1039 assert.ok(path.scope.declares("baz"));
1040 assert.strictEqual(path.scope.lookup("baz"), path.scope);
1041
1042 assert.strictEqual(path.scope.lookup("qux"), null);
1043 assert.strictEqual(globalScope.lookup("baz"), null);
1044
1045 this.traverse(path);
1046 }
1047 });
1048 });
1049 });
1050
1051 describe("scope methods", function () {
1052 var scope = [
1053 "var foo = 42;",
1054 "function bar(baz) {",
1055 " return baz + foo;",
1056 "}",
1057 "var nom = function rom(pom) {",
1058 " var zom;",
1059 " return rom(pom);",
1060 "};"
1061 ];
1062
1063 it("getBindings should get local and global scope bindings", function() {
1064 var ast = parse(scope.join("\n"));
1065 var checked = [];
1066
1067 types.visit(ast, {
1068 visitProgram: function(path) {
1069 var bindings = path.scope.getBindings();
1070 assert.deepEqual(["bar", "foo", "nom"], Object.keys(bindings).sort());
1071 assert.equal(1, bindings.foo.length);
1072 assert.equal(1, bindings.bar.length);
1073 checked.push(path.node);
1074 this.traverse(path);
1075 },
1076
1077 visitFunctionDeclaration: function(path) {
1078 var bindings = path.scope.getBindings();
1079 assert.deepEqual(["baz"], Object.keys(bindings));
1080 assert.equal(1, bindings.baz.length);
1081 checked.push(path.node);
1082 this.traverse(path);
1083 },
1084
1085 visitReturnStatement: function(path) {
1086 var node = path.node;
1087 if (n.CallExpression.check(node.argument) &&
1088 node.argument.callee.name === "rom") {
1089 var bindings = path.scope.getBindings();
1090 assert.deepEqual(["pom", "rom", "zom"], Object.keys(bindings).sort());
1091 checked.push(node);
1092 }
1093 this.traverse(path);
1094 }
1095 });
1096
1097 assert.deepEqual(
1098 checked.map(function(node) { return node.type; }),
1099 ['Program', 'FunctionDeclaration', 'ReturnStatement']
1100 );
1101 });
1102
1103 it("getBindings should work for import statements (esprima-fb)", function() {
1104 var ast = require("esprima-fb").parse(
1105 [
1106 "import {x, y as z} from 'xy';",
1107 "import xyDefault from 'xy';",
1108 "import * as xyNamespace from 'xy';"
1109 ].join("\n"),
1110 {sourceType: "module"}
1111 );
1112
1113 var names;
1114
1115 types.visit(ast, {
1116 visitProgram: function(path) {
1117 names = Object.keys(path.scope.getBindings()).sort();
1118 this.traverse(path);
1119 }
1120 });
1121
1122 assert.deepEqual(names, ["x", "xyDefault", "xyNamespace", "z"]);
1123 });
1124
1125 it("getBindings should work for import statements (acorn)", function() {
1126 var ast = babylonParse([
1127 "import {x, y as z} from 'xy';",
1128 "import xyDefault from 'xy';",
1129 "import * as xyNamespace from 'xy';"
1130 ].join("\n"), {
1131 sourceType: "module",
1132 ecmaVersion: 6
1133 });
1134
1135 var names;
1136
1137 types.visit(ast, {
1138 visitProgram: function(path) {
1139 names = Object.keys(path.scope.getBindings()).sort();
1140 this.traverse(path);
1141 }
1142 });
1143
1144 assert.deepEqual(names, ["x", "xyDefault", "xyNamespace", "z"]);
1145 });
1146
1147 it("should work for ES6 syntax (espree)", function() {
1148 var names;
1149
1150 var ast = require("espree").parse([
1151 "var zap;",
1152 "export default function(zom) {",
1153 " var innerFn = function(zip) {};",
1154 " return innerFn(zom);",
1155 "};"
1156 ].join("\n"), {
1157 sourceType: "module",
1158 ecmaVersion: 6
1159 });
1160
1161 types.visit(ast, {
1162 visitFunctionDeclaration: function(path) {
1163 names = Object.keys(path.scope.lookup("zap").getBindings()).sort();
1164 assert.deepEqual(names, ["zap"]);
1165 this.traverse(path);
1166 }
1167 });
1168 });
1169
1170 it("should inject temporary into current scope", function() {
1171 var ast = parse(scope.join("\n"));
1172 var bindings;
1173
1174 types.visit(ast, {
1175 visitProgram: function(path) {
1176 path.scope.injectTemporary();
1177 bindings = path.scope.getBindings();
1178 assert.deepEqual(["bar", "foo", "nom", "t$0$0"], Object.keys(bindings).sort());
1179 this.traverse(path);
1180 },
1181
1182 visitFunctionDeclaration: function(path) {
1183 path.scope.injectTemporary(
1184 path.scope.declareTemporary("t$")
1185 )
1186 bindings = path.scope.getBindings();
1187 assert.deepEqual(["baz", "t$1$0"], Object.keys(bindings));
1188 this.traverse(path);
1189 }
1190 });
1191 });
1192
1193 it("declareTemporary should use distinct names in nested scopes", function() {
1194 var ast = parse(scope.join("\n"));
1195 var globalVarDecl;
1196 var barVarDecl;
1197 var romVarDecl;
1198
1199 types.visit(ast, {
1200 visitProgram: function(path) {
1201 path.get("body").unshift(
1202 globalVarDecl = b.variableDeclaration("var", [
1203 b.variableDeclarator(
1204 path.scope.declareTemporary("$"),
1205 b.literal("global")
1206 ),
1207 b.variableDeclarator(
1208 path.scope.declareTemporary("$"),
1209 b.literal("global")
1210 )
1211 ])
1212 );
1213
1214 this.traverse(path);
1215 },
1216
1217 visitFunction: function(path) {
1218 var funcId = path.value.id;
1219
1220 var varDecl = b.variableDeclaration("var", [
1221 b.variableDeclarator(
1222 path.scope.declareTemporary("$"),
1223 b.literal(funcId.name + 1)
1224 ),
1225 b.variableDeclarator(
1226 path.scope.declareTemporary("$"),
1227 b.literal(funcId.name + 2)
1228 )
1229 ]);
1230
1231 path.get("body", "body").unshift(varDecl);
1232
1233 if (funcId.name === "bar") {
1234 barVarDecl = varDecl;
1235 } else if (funcId.name === "rom") {
1236 romVarDecl = varDecl;
1237 }
1238
1239 this.traverse(path);
1240 }
1241 });
1242
1243 assert.strictEqual(globalVarDecl.declarations[0].id.name, "$0$0");
1244 assert.strictEqual(globalVarDecl.declarations[1].id.name, "$0$1");
1245 assert.strictEqual(barVarDecl.declarations[0].id.name, "$1$0");
1246 assert.strictEqual(barVarDecl.declarations[1].id.name, "$1$1");
1247 assert.strictEqual(romVarDecl.declarations[0].id.name, "$1$0");
1248 assert.strictEqual(romVarDecl.declarations[1].id.name, "$1$1");
1249 });
1250 });
1251
1252 describe("catch block scope", function() {
1253 var catchWithVarDecl = [
1254 "function foo(e) {",
1255 " try {",
1256 " bar();",
1257 " } catch (e) {",
1258 " var f = e + 1;",
1259 " return function(g) {",
1260 " return e + g;",
1261 " };",
1262 " }",
1263 " return f;",
1264 "}"
1265 ];
1266
1267 var path = new NodePath(parse(catchWithVarDecl.join("\n")));
1268 var fooPath = path.get("body", 0);
1269 var fooScope = fooPath.scope;
1270 var catchPath = fooPath.get("body", "body", 0, "handler");
1271 var catchScope = catchPath.scope;
1272
1273 it("should not affect outer scope declarations", function() {
1274 n.FunctionDeclaration.assert(fooScope.node);
1275 assert.strictEqual(fooScope.declares("e"), true);
1276 assert.strictEqual(fooScope.declares("f"), true);
1277 assert.strictEqual(fooScope.lookup("e"), fooScope);
1278 });
1279
1280 it("should declare only the guard parameter", function() {
1281 n.CatchClause.assert(catchScope.node);
1282 assert.strictEqual(catchScope.declares("e"), true);
1283 assert.strictEqual(catchScope.declares("f"), false);
1284 assert.strictEqual(catchScope.lookup("e"), catchScope);
1285 assert.strictEqual(catchScope.lookup("f"), fooScope);
1286 });
1287
1288 it("should shadow only the parameter in nested scopes", function() {
1289 var closurePath = catchPath.get("body", "body", 1, "argument");
1290 var closureScope = closurePath.scope;
1291 n.FunctionExpression.assert(closureScope.node);
1292 assert.strictEqual(closureScope.declares("e"), false);
1293 assert.strictEqual(closureScope.declares("f"), false);
1294 assert.strictEqual(closureScope.declares("g"), true);
1295 assert.strictEqual(closureScope.lookup("g"), closureScope);
1296 assert.strictEqual(closureScope.lookup("e"), catchScope);
1297 assert.strictEqual(closureScope.lookup("f"), fooScope);
1298 });
1299 });
1300
1301 describe("array and object pattern scope", function() {
1302
1303 function scopeFromPattern(pattern) {
1304 return new NodePath(
1305 b.program([
1306 b.variableDeclaration('var', [
1307 b.variableDeclarator(pattern, null)
1308 ])
1309 ])
1310 ).scope;
2226 function checkExp(exp) {
2227 BigIntLiteral.assert(exp, true);
2228
2229 assert.strictEqual(
2230 exp.extra.rawValue,
2231 exp.value
2232 );
2233
2234 assert.strictEqual(
2235 exp.extra.raw,
2236 exp.value + "n"
2237 );
2238
2239 delete exp.extra;
2240
2241 BigIntLiteral.assert(exp, true);
2242
2243 var extra = types.getFieldValue(exp, "extra");
2244
2245 assert.strictEqual(
2246 extra.rawValue,
2247 exp.value
2248 );
2249
2250 assert.strictEqual(
2251 extra.raw,
2252 exp.value + "n"
2253 );
13112254 }
13122255
1313 // ObjectPattern with Property and SpreadProperty
1314 // ArrayPattern with SpreadElement
1315 describe("esprima", function() {
1316 var types = require('../fork')([
1317 require("../def/esprima")
1318 ]);
1319 var b = types.builders;
1320
1321 var objectPattern;
1322 var arrayPattern;
1323
1324 beforeEach(function() {
1325 // {a, b: c, ...d}
1326 objectPattern = b.objectPattern([
1327 b.property('init', b.identifier('a'), b.identifier('a')),
1328 b.property('init', b.identifier('b'), b.identifier('c')),
1329 b.spreadProperty(b.identifier('d')),
1330 ]);
1331
1332 // [foo, bar, ...baz]
1333 arrayPattern = b.arrayPattern([
1334 b.identifier('foo'),
1335 b.identifier('bar'),
1336 b.spreadElement(b.identifier('baz'))
1337 ]);
1338 });
1339
1340 it("should handle object patterns variable declarations", function() {
1341 var scope = scopeFromPattern(objectPattern);
1342
1343 assert.strictEqual(scope.declares("a"), true);
1344 assert.strictEqual(scope.declares("b"), false);
1345 assert.strictEqual(scope.declares("c"), true);
1346 assert.strictEqual(scope.declares("d"), true);
1347 });
1348
1349 it("should handle array patterns in variable declarations", function() {
1350 var scope = scopeFromPattern(arrayPattern);
1351
1352 assert.strictEqual(scope.declares("foo"), true);
1353 assert.strictEqual(scope.declares("bar"), true);
1354 assert.strictEqual(scope.declares("baz"), true);
1355 });
1356
1357 it("should handle nested patterns in variable declarations", function() {
1358 // {a, b: c, ...d, e: [foo, bar, ...baz]}
1359 objectPattern.properties.push(
1360 b.property('init', b.identifier('e'), arrayPattern)
1361 );
1362
1363 var scope = scopeFromPattern(objectPattern);
1364 assert.strictEqual(scope.declares("a"), true);
1365 assert.strictEqual(scope.declares("b"), false);
1366 assert.strictEqual(scope.declares("c"), true);
1367 assert.strictEqual(scope.declares("d"), true);
1368 assert.strictEqual(scope.declares("e"), false);
1369 assert.strictEqual(scope.declares("foo"), true);
1370 assert.strictEqual(scope.declares("bar"), true);
1371 assert.strictEqual(scope.declares("baz"), true);
1372 });
1373 });
1374
1375 // ObjectPattern with PropertyPattern and SpreadPropertyPattern
1376 // ArrayPatterhn with SpreadElementPattern
1377 describe("Mozilla Parser API", function() {
1378 var types = require('../fork')([
1379 require("../def/core"),
1380 require("../def/es6"),
1381 require("../def/es7"),
1382 require("../def/mozilla"),
1383 ]);
1384 var b = types.builders;
1385
1386 var objectPattern;
1387 var arrayPattern;
1388
1389 beforeEach(function() {
1390 // {a, b: c, ...d}
1391 objectPattern = b.objectPattern([
1392 b.propertyPattern(b.identifier('a'), b.identifier('a')),
1393 b.propertyPattern(b.identifier('b'), b.identifier('c')),
1394 b.spreadPropertyPattern(b.identifier('d')),
1395 ]);
1396
1397 // [foo, bar, ...baz]
1398 arrayPattern = b.arrayPattern([
1399 b.identifier('foo'),
1400 b.identifier('bar'),
1401 b.spreadElementPattern(b.identifier('baz'))
1402 ]);
1403 });
1404
1405 it("should handle object patterns variable declarations", function() {
1406 var scope = scopeFromPattern(objectPattern);
1407
1408 assert.strictEqual(scope.declares("a"), true);
1409 assert.strictEqual(scope.declares("b"), false);
1410 assert.strictEqual(scope.declares("c"), true);
1411 assert.strictEqual(scope.declares("d"), true);
1412 });
1413
1414 it("should handle array patterns in variable declarations", function() {
1415 var scope = scopeFromPattern(arrayPattern);
1416
1417 assert.strictEqual(scope.declares("foo"), true);
1418 assert.strictEqual(scope.declares("bar"), true);
1419 assert.strictEqual(scope.declares("baz"), true);
1420 });
1421
1422 it("should handle nested patterns in variable declarations", function() {
1423 // {a, b: c, ...d, e: [foo, bar, ...baz]}
1424 objectPattern.properties.push(
1425 b.propertyPattern(b.identifier('e'), arrayPattern)
1426 );
1427
1428 var scope = scopeFromPattern(objectPattern);
1429 assert.strictEqual(scope.declares("a"), true);
1430 assert.strictEqual(scope.declares("b"), false);
1431 assert.strictEqual(scope.declares("c"), true);
1432 assert.strictEqual(scope.declares("d"), true);
1433 assert.strictEqual(scope.declares("e"), false);
1434 assert.strictEqual(scope.declares("foo"), true);
1435 assert.strictEqual(scope.declares("bar"), true);
1436 assert.strictEqual(scope.declares("baz"), true);
1437 });
1438 });
1439 });
1440
1441 describe("types.defineMethod", function() {
1442 function at(loc) {
1443 types.namedTypes.SourceLocation.assert(loc);
1444 this.loc = loc;
1445 }
1446
1447 var thisExpr = b.thisExpression();
1448
1449 it("should allow defining an .at method", function() {
1450 assert.strictEqual(types.defineMethod("at", at), void 0);
1451 assert.strictEqual(thisExpr.loc, null);
1452
1453 thisExpr.at(b.sourceLocation(
1454 b.position(1, 0),
1455 b.position(1, 4)
1456 ));
1457
1458 assert.strictEqual(thisExpr.loc.start.line, 1);
1459 assert.strictEqual(thisExpr.loc.start.column, 0);
1460 assert.strictEqual(thisExpr.loc.end.line, 1);
1461 assert.strictEqual(thisExpr.loc.end.column, 4);
1462 });
1463
1464 it("should allow methods to be removed", function() {
1465 // Now try removing the method.
1466 assert.strictEqual(types.defineMethod("at"), at);
1467 assert.strictEqual(thisExpr.at, void 0);
1468 assert.strictEqual("at" in thisExpr, false);
1469 });
1470 });
1471
1472 describe("types.visit", function() {
1473 var objProp;
1474
1475 beforeEach(function() {
1476 objProp = b.memberExpression(
1477 b.identifier("object"),
1478 b.identifier("property"),
1479 false
1480 );
1481 });
1482
1483 it("should be identical to PathVisitor.visit", function() {
1484 assert.strictEqual(types.visit, PathVisitor.visit);
1485 });
1486
1487 it("should work with no visitors", function() {
1488 var foo = b.identifier("foo");
1489 assert.strictEqual(types.visit(foo), foo);
1490 });
1491
1492 it("should allow simple tree modifications", function() {
1493 var bar = types.visit(b.identifier("foo"), {
1494 visitIdentifier: function(path) {
1495 assert.ok(path instanceof NodePath);
1496 path.value.name = "bar";
1497 return false;
1498 }
1499 });
1500
1501 n.Identifier.assert(bar);
1502 assert.strictEqual(bar.name, "bar");
1503 });
1504
1505 it("should complain about missing this.traverse", function() {
1506 try {
1507 types.visit(objProp, {
1508 visitIdentifier: function(path) {
1509 // buh?
1510 }
1511 });
1512
1513 assert.ok(false, "should have thrown an exception");
1514
1515 } catch (err) {
1516 assert.strictEqual(
1517 err.message,
1518 "Must either call this.traverse or return false in visitIdentifier"
1519 );
1520 }
1521 });
1522
1523 it("should support this.traverse", function() {
1524 var idNames = [];
1525
1526 types.visit(objProp, {
1527 visitMemberExpression: function(path) {
1528 this.traverse(path, {
1529 visitIdentifier: function(path) {
1530 idNames.push("*" + path.value.name + "*");
1531 return false;
1532 }
1533 });
1534
1535 path.get("object", "name").replace("asdfasdf");
1536 path.get("property", "name").replace("zxcvzxcv");
1537
1538 this.visit(path.get("property"));
1539 },
1540
1541 visitIdentifier: function(path) {
1542 idNames.push(path.value.name);
1543 return false;
1544 }
1545 });
1546
1547 assert.deepEqual(idNames, ["*object*", "*property*", "zxcvzxcv"]);
1548
1549 idNames.length = 0;
1550
1551 types.visit(objProp, {
1552 visitMemberExpression: function(path) {
1553 path.get("object", "name").replace("asdfasdf");
1554 path.get("property", "name").replace("zxcvzxcv");
1555 this.traverse(path, {
1556 visitIdentifier: function(path) {
1557 idNames.push(path.value.name);
1558 return false;
1559 }
1560 });
1561 }
1562 });
1563
1564 assert.deepEqual(idNames, ["asdfasdf", "zxcvzxcv"]);
1565 });
1566
1567 it("should support this.replace", function() {
1568 var seqExpr = b.sequenceExpression([
1569 b.literal("asdf"),
1570 b.identifier("zxcv"),
1571 b.thisExpression()
1572 ]);
1573
1574 types.visit(seqExpr, {
1575 visitIdentifier: function(path) {
1576 assert.strictEqual(path.value.name, "zxcv");
1577 path.replace(
1578 b.identifier("foo"),
1579 b.identifier("bar")
1580 );
1581 return false;
1582 }
1583 });
1584
1585 assert.strictEqual(seqExpr.expressions.length, 4);
1586
1587 var foo = seqExpr.expressions[1];
1588 n.Identifier.assert(foo);
1589 assert.strictEqual(foo.name, "foo");
1590
1591 var bar = seqExpr.expressions[2];
1592 n.Identifier.assert(bar);
1593 assert.strictEqual(bar.name, "bar");
1594
1595 types.visit(seqExpr, {
1596 visitIdentifier: function(path) {
1597 if (path.value.name === "foo") {
1598 path.replace(path.value, path.value);
1599 }
1600
1601 return false;
1602 }
1603 });
1604
1605 assert.strictEqual(seqExpr.expressions.length, 5);
1606
1607 var foo = seqExpr.expressions[1];
1608 n.Identifier.assert(foo);
1609 assert.strictEqual(foo.name, "foo");
1610
1611 var foo = seqExpr.expressions[2];
1612 n.Identifier.assert(foo);
1613 assert.strictEqual(foo.name, "foo");
1614
1615 var bar = seqExpr.expressions[3];
1616 n.Identifier.assert(bar);
1617 assert.strictEqual(bar.name, "bar");
1618
1619 types.visit(seqExpr, {
1620 visitLiteral: function(path) {
1621 path.replace();
1622 return false;
1623 },
1624
1625 visitIdentifier: function(path) {
1626 if (path.value.name === "bar") {
1627 path.replace();
1628 }
1629
1630 return false;
1631 }
1632 });
1633
1634 assert.strictEqual(seqExpr.expressions.length, 3);
1635
1636 var first = seqExpr.expressions[0];
1637 n.Identifier.assert(first);
1638 assert.strictEqual(first.name, "foo");
1639
1640 var second = seqExpr.expressions[1];
1641 assert.strictEqual(second, first);
1642
1643 var third = seqExpr.expressions[2];
1644 n.ThisExpression.assert(third);
1645 });
1646
1647 it("should reuse old VisitorContext objects", function() {
1648 var objectContext;
1649 var propertyContext;
1650
1651 types.visit(objProp, {
1652 visitIdentifier: function(path) {
1653 assert.strictEqual(this.needToCallTraverse, true);
1654 this.traverse(path);
1655 assert.strictEqual(path.name, path.value.name);
1656 if (path.name === "object") {
1657 objectContext = this;
1658 } else if (path.name === "property") {
1659 propertyContext = this;
1660 }
1661 }
1662 });
1663
1664 assert.ok(objectContext);
1665 assert.ok(propertyContext);
1666 assert.strictEqual(objectContext, propertyContext);
1667 });
1668
1669 it("should dispatch to closest visitSupertype method", function() {
1670 var foo = b.identifier("foo");
1671 var bar = b.identifier("bar");
1672 var callExpr = b.callExpression(
1673 b.memberExpression(
1674 b.functionExpression(
1675 b.identifier("add"),
1676 [foo, bar],
1677 b.blockStatement([
1678 b.returnStatement(
1679 b.binaryExpression("+", foo, bar)
1680 )
1681 ])
1682 ),
1683 b.identifier("bind"),
1684 false
1685 ),
1686 [b.thisExpression()]
1687 );
1688
1689 var nodes = [];
1690 var expressions = [];
1691 var identifiers = [];
1692 var statements = [];
1693 var returnStatements = [];
1694 var functions = [];
1695
1696 function makeVisitorMethod(array) {
1697 return function(path) {
1698 array.push(path.value);
1699 this.traverse(path);
1700 };
1701 }
1702
1703 types.visit(callExpr, {
1704 visitNode: makeVisitorMethod(nodes),
1705 visitExpression: makeVisitorMethod(expressions),
1706 visitIdentifier: makeVisitorMethod(identifiers),
1707 visitStatement: makeVisitorMethod(statements),
1708 visitReturnStatement: makeVisitorMethod(returnStatements),
1709 visitFunction: makeVisitorMethod(functions)
1710 });
1711
1712 function check(array) {
1713 var rest = Array.prototype.slice.call(arguments, 1);
1714 assert.strictEqual(array.length, rest.length);
1715 for (var i = 0; i < rest.length; ++i) {
1716 assert.strictEqual(array[i], rest[i]);
1717 }
1718 }
1719
1720 check(nodes);
1721
1722 check(expressions,
1723 callExpr,
1724 callExpr.callee,
1725 callExpr.callee.object.body.body[0].argument,
1726 callExpr.arguments[0]);
1727
1728 check(identifiers,
1729 callExpr.callee.object.id,
1730 foo,
1731 bar,
1732 foo,
1733 bar,
1734 callExpr.callee.property);
1735
1736 check(statements,
1737 callExpr.callee.object.body);
1738
1739 check(returnStatements,
1740 callExpr.callee.object.body.body[0]);
1741
1742 check(functions,
1743 callExpr.callee.object);
1744 });
1745
1746 it("should replace this.currentPath with returned value", function() {
1747 assert.strictEqual(objProp.computed, false);
1748
1749 types.visit(objProp, {
1750 visitIdentifier: function(path) {
1751 if (path.value.name === "property") {
1752 path.parent.get("computed").replace(true);
1753 return b.callExpression(
1754 b.memberExpression(
1755 b.thisExpression(),
1756 b.identifier("toString"),
1757 false
1758 ),
1759 []
1760 );
1761 }
1762
1763 this.traverse(path);
1764 },
1765
1766 visitThisExpression: function(path) {
1767 return b.identifier("self");
1768 }
1769 });
1770
1771 assert.strictEqual(objProp.computed, true);
1772 n.CallExpression.assert(objProp.property);
1773
1774 var callee = objProp.property.callee;
1775 n.MemberExpression.assert(callee);
1776
1777 n.Identifier.assert(callee.object);
1778 assert.strictEqual(callee.object.name, "self");
1779
1780 n.Identifier.assert(callee.property);
1781 assert.strictEqual(callee.property.name, "toString");
1782
1783 assert.deepEqual(objProp.property.arguments, []);
1784 });
1785 });
1786
1787 describe("path.shift", function() {
1788 it("should work like Array.prototype.shift", function() {
1789 var path = new NodePath({
1790 elements: [0, "foo", true]
1791 });
1792
1793 var first = path.get("elements", 0);
1794 assert.strictEqual(first.name, 0);
1795
1796 var second = path.get("elements", 1);
1797 assert.strictEqual(second.name, 1);
1798
1799 var third = path.get("elements", 2);
1800 assert.strictEqual(third.name, 2);
1801
1802 assert.strictEqual(path.get("elements", "length").value, 3);
1803
1804 assert.strictEqual(path.get("elements").shift(), first.value);
1805 assert.strictEqual(path.get("elements", "length").value, 2);
1806 assert.strictEqual(path.get("elements", 0), second);
1807 assert.strictEqual(path.get("elements", 1), third);
1808 assert.strictEqual(second.name, 0);
1809 assert.strictEqual(third.name, 1);
1810
1811 assert.strictEqual(path.get("elements").shift(), second.value);
1812 assert.strictEqual(path.get("elements", "length").value, 1);
1813 assert.strictEqual(path.get("elements", 0), third);
1814 assert.strictEqual(third.name, 0);
1815
1816 assert.strictEqual(path.get("elements").shift(), third.value);
1817 assert.strictEqual(path.get("elements").shift(), void 0);
1818 assert.strictEqual(path.get("elements", "length").value, 0);
1819 });
1820
1821 it("should throw when path.value not an array", function() {
1822 assert.throws(function() {
1823 new NodePath({ foo: 42 }).get("foo").shift();
1824 });
1825 });
1826 });
1827
1828 describe("path.unshift", function() {
1829 it("should work like Array.prototype.unshift", function() {
1830 var path = new NodePath(b.sequenceExpression([]));
1831 var elems = path.get("expressions");
1832
1833 var one = b.literal(1);
1834 var two = b.literal(2);
1835 var three = b.literal(3);
1836 var four = b.literal(4);
1837 var five = b.literal(5);
1838
1839 assert.strictEqual(elems.get(1).parentPath, elems);
1840 assert.strictEqual(elems.get(1).node, path.value);
1841 assert.strictEqual(elems.get(1).parent, null);
1842
1843 assert.strictEqual(elems.get("length").value, 0);
1844 elems.unshift(three, four, five);
1845 assert.deepEqual(path.value.expressions, [three, four, five]);
1846 var fourPath = elems.get(1);
1847 assert.strictEqual(fourPath.value.value, 4);
1848 elems.unshift(one, two);
1849 assert.deepEqual(elems.value, [one, two, three, four, five]);
1850 elems.unshift();
1851 assert.deepEqual(elems.value, [one, two, three, four, five]);
1852 assert.strictEqual(fourPath.name, 3);
1853 assert.strictEqual(elems.get("length").value, 5);
1854
1855 assert.strictEqual(elems.get(1).parentPath, elems);
1856 assert.strictEqual(elems.get(1).node, two);
1857 assert.strictEqual(elems.get(1).parent, path);
1858 });
1859
1860 it("should throw when path.value not an array", function() {
1861 assert.throws(function() {
1862 new NodePath({ foo: 42 }).get("foo").unshift();
1863 });
1864 });
1865 });
1866
1867 describe("path.push", function() {
1868 it("should work like Array.prototype.push", function() {
1869 var path = new NodePath({ elements: [0] });
1870 var elems = path.get("elements");
1871 assert.strictEqual(elems.get("length").value, 1);
1872 elems.push(1, 2, 3);
1873 assert.deepEqual(path.value.elements, [0, 1, 2, 3]);
1874 var two = elems.get(2);
1875 assert.strictEqual(two.value, 2);
1876 elems.push(4, 5);
1877 assert.deepEqual(elems.value, [0, 1, 2, 3, 4, 5]);
1878 elems.push();
1879 assert.deepEqual(elems.value, [0, 1, 2, 3, 4, 5]);
1880 assert.strictEqual(two.name, 2);
1881 assert.strictEqual(elems.get("length").value, 6);
1882 });
1883
1884 it("should throw when path.value not an array", function() {
1885 assert.throws(function() {
1886 new NodePath({ foo: 42 }).get("foo").push("asdf");
1887 });
1888 });
1889 });
1890
1891 describe("path.pop", function() {
1892 it("should work like Array.prototype.pop", function() {
1893 var path = new NodePath({
1894 elements: [0, "foo", true]
1895 });
1896
1897 var first = path.get("elements", 0);
1898 assert.strictEqual(first.name, 0);
1899
1900 var second = path.get("elements", 1);
1901 assert.strictEqual(second.name, 1);
1902
1903 var third = path.get("elements", 2);
1904 assert.strictEqual(third.name, 2);
1905
1906 assert.strictEqual(path.get("elements", "length").value, 3);
1907
1908 assert.strictEqual(path.get("elements").pop(), third.value);
1909 assert.strictEqual(path.get("elements", "length").value, 2);
1910 assert.strictEqual(path.get("elements", 0), first);
1911 assert.strictEqual(path.get("elements", 1), second);
1912 assert.strictEqual(first.name, 0);
1913 assert.strictEqual(second.name, 1);
1914
1915 assert.strictEqual(path.get("elements").pop(), second.value);
1916 assert.strictEqual(path.get("elements", "length").value, 1);
1917 assert.strictEqual(path.get("elements", 0), first);
1918 assert.strictEqual(first.name, 0);
1919
1920 assert.strictEqual(path.get("elements").pop(), first.value);
1921 assert.strictEqual(path.get("elements").pop(), void 0);
1922 assert.strictEqual(path.get("elements", "length").value, 0);
1923 });
1924
1925 it("should throw when path.value not an array", function() {
1926 assert.throws(function() {
1927 new NodePath({ foo: 42 }).get("foo").pop();
1928 });
1929 });
1930 });
1931
1932 describe("path.insertAt", function() {
1933 it("should insert nodes at the given index", function() {
1934 var path = new NodePath({
1935 elements: [0, "foo", true]
1936 });
1937
1938 var elems = path.get("elements");
1939 elems.insertAt(1, "a", "b");
1940 assert.deepEqual(elems.value, [0, "a", "b", "foo", true]);
1941
1942 elems.insertAt(elems.get("length").value + 1, []);
1943 assert.deepEqual(elems.value, [0, "a", "b", "foo", true,, []]);
1944 assert.strictEqual(elems.get("length").value, 7);
1945
1946 elems.insertAt(elems.get("length").value + 12345);
1947 assert.deepEqual(elems.value, [0, "a", "b", "foo", true,, []]);
1948 assert.strictEqual(elems.get("length").value, 7);
1949
1950 elems.insertAt(-2, -2, -1);
1951 assert.deepEqual(elems.value, [-2, -1, 0, "a", "b", "foo", true,, []]);
1952 assert.strictEqual(elems.get("length").value, 9);
1953 });
1954
1955 it("should throw when path.value not an array", function() {
1956 assert.throws(function() {
1957 new NodePath({ foo: 42 }).get("foo").insertAt(0);
1958 });
1959 });
1960 });
1961
1962 describe("path.insertBefore", function() {
1963 it("should insert nodes before the current path", function() {
1964 var zero = b.literal(0);
1965 var one = b.literal(1);
1966 var two = b.literal(2);
1967 var foo = b.literal("foo");
1968 var truth = b.literal(true);
1969
1970 var path = new NodePath(b.sequenceExpression([zero, foo, truth]));
1971 var fooPath = path.get("expressions", 1);
1972 var truePath = path.get("expressions", 2);
1973 fooPath.insertBefore(one, two);
1974 assert.deepEqual(
1975 fooPath.parent.node.expressions,
1976 [zero, one, two, foo, truth]
1977 );
1978
1979 assert.strictEqual(path.get("expressions", 3), fooPath);
1980 assert.strictEqual(fooPath.value.value, "foo");
1981
1982 assert.strictEqual(path.get("expressions", 4), truePath);
1983 assert.strictEqual(truePath.value.value, true);
1984 });
1985
1986 it("should throw when path.parentPath.value not an array", function() {
1987 assert.throws(function() {
1988 new NodePath({ foo: 42 }).get("foo").insertBefore(0);
1989 });
1990 });
1991 });
1992
1993 describe("path.insertAfter", function() {
1994 it("should insert nodes after the current path", function() {
1995 var zero = b.literal(0);
1996 var one = b.literal(1);
1997 var two = b.literal(2);
1998 var foo = b.literal("foo");
1999 var truth = b.literal(true);
2000
2001 var path = new NodePath(b.sequenceExpression([zero, foo, truth]));
2002 var fooPath = path.get("expressions", 1);
2003 var truePath = path.get("expressions", 2);
2004 fooPath.insertAfter(one, two);
2005 assert.deepEqual(
2006 fooPath.parent.node.expressions,
2007 [zero, foo, one, two, truth]
2008 );
2009
2010 assert.strictEqual(path.get("expressions", 1), fooPath);
2011 assert.strictEqual(fooPath.value.value, "foo");
2012
2013 assert.strictEqual(path.get("expressions", 2).value.value, 1);
2014 assert.strictEqual(path.get("expressions", 3).value.value, 2);
2015
2016 assert.strictEqual(path.get("expressions", 4), truePath);
2017 assert.strictEqual(truePath.value.value, true);
2018
2019 var three = b.literal(3)
2020 truePath.insertAfter(three);
2021 assert.deepEqual(
2022 fooPath.parent.node.expressions,
2023 [zero, foo, one, two, truth, three]
2024 );
2025 });
2026
2027 it("should throw when path.parentPath.value not an array", function() {
2028 assert.throws(function() {
2029 new NodePath({ foo: 42 }).get("foo").insertAfter(0);
2030 });
2031 });
2032 });
2033
2034 describe("types.astNodesAreEquivalent", function() {
2035 it("should work for simple values", function() {
2036 types.astNodesAreEquivalent.assert(1, 2 - 1);
2037 types.astNodesAreEquivalent.assert("1", 1);
2038 types.astNodesAreEquivalent.assert(true, !false);
2039
2040 var d1 = new Date;
2041 var d2 = new Date(+d1);
2042 assert.notStrictEqual(d1, d2);
2043 types.astNodesAreEquivalent.assert(d1, d2);
2044
2045 types.astNodesAreEquivalent.assert(/x/, /x/);
2046 assert.strictEqual(types.astNodesAreEquivalent(/x/g, /x/), false);
2047 });
2048
2049 it("should work for arrays", function() {
2050 types.astNodesAreEquivalent.assert([], [1, 2, 3].slice(10));
2051 types.astNodesAreEquivalent.assert([1, 2, 3], [1].concat(2, [3]));
2052 types.astNodesAreEquivalent.assert([1,, 3], [1,, 3,]);
2053 assert.strictEqual(
2054 types.astNodesAreEquivalent([1,, 3], [1, void 0, 3]),
2055 false
2056 );
2057 });
2058
2059 it("should work for objects", function() {
2060 types.astNodesAreEquivalent.assert({
2061 foo: 42,
2062 bar: "asdf"
2063 }, {
2064 bar: "asdf",
2065 foo: 42
2066 });
2067
2068 assert.strictEqual(types.astNodesAreEquivalent({
2069 foo: 42,
2070 bar: "asdf",
2071 baz: true
2072 }, {
2073 bar: "asdf",
2074 foo: 42
2075 }), false);
2076
2077 assert.strictEqual(types.astNodesAreEquivalent({
2078 foo: 42,
2079 bar: "asdf"
2080 }, {
2081 bar: "asdf",
2082 foo: 42,
2083 baz: true
2084 }), false);
2085 });
2086
2087 it("should work for AST nodes", function() {
2088 function check(src1, src2) {
2089 types.astNodesAreEquivalent.assert(parse(src1), parse(src2));
2090 }
2091
2092 function checkNot(src1, src2) {
2093 var ast1 = parse(src1, { loc: true, range: true });
2094 var ast2 = parse(src2, { loc: true });
2095
2096 assert.throws(function() {
2097 types.astNodesAreEquivalent.assert(ast1, ast2);
2098 });
2099
2100 var problemPath = [];
2101 types.astNodesAreEquivalent(parse(src1), parse(src2), problemPath);
2102 assert.notStrictEqual(problemPath.length, 0);
2103
2104 var a = ast1;
2105 var b = ast2;
2106
2107 problemPath.forEach(function(name) {
2108 assert.strictEqual(name in a, true);
2109 assert.strictEqual(name in b, true);
2110 a = a[name];
2111 b = b[name];
2112 });
2113
2114 assert.notStrictEqual(a, b);
2115 }
2116
2117 check("1\n;", "1;");
2118
2119 check("console.log(this.toString(36));", [
2120 "// leading comment",
2121 "console.log(",
2122 " this.toString(36)",
2123 "/* trailing comment */)"
2124 ].join("\n"));
2125
2126 check("foo()", "foo /*anonymous*/ ()");
2127
2128 check("new (bar(1,2)(3,4)).baz.call(null)",
2129 "new( bar( 1,2) \n (3,4)). baz.call( null)");
2130
2131 check([
2132 "(function(x) {",
2133 " Foo = /asdf/.test(x);",
2134 "}());"
2135 ].join("\n"), [
2136 "(function(x) {",
2137 " Foo = /asdf/.test(x);",
2138 "})();"
2139 ].join("\n\n"));
2140
2141 checkNot([
2142 "(function(x) {",
2143 " Foo = /asdf/.test(x);",
2144 "}());"
2145 ].join("\n"), [
2146 "(function(x) {",
2147 " Foo = /asdf/.test(x);",
2148 "})('~asdf~');"
2149 ].join("\n\n"));
2150
2151 checkNot([
2152 "(function(x) {",
2153 " var Foo = /asdf/.test(x);",
2154 "}());"
2155 ].join("\n"), [
2156 "(function(x) {",
2157 " Foo = /asdf/.test(x);",
2158 "})(/*'~asdf~'*/);"
2159 ].join("\n\n"));
2160 });
2161 });
2162
2163 describe("RegExpLiteral nodes", function() {
2164 it("should have a default-computable .regex field", function() {
2165 var ast = parse('/x*/gmi.test("xxx")');
2166 var regExp = ast.body[0].expression.callee.object;
2167
2168 n.Literal.assert(regExp);
2169 isRegExp.assert(regExp.value);
2170
2171 var regex = types.getFieldValue(regExp, "regex");
2172
2173 regex.flags = regex.flags.split("").sort().join("");
2174
2175 assert.deepEqual(regex, {
2176 pattern: "x*",
2177 flags: "gim"
2178 });
2179
2180 types.Type.fromObject({
2181 pattern: isString,
2182 flags: isString
2183 }).assert(regex);
2184 });
2185
2186 it("should typecheck with explicit .regex field", function() {
2187 var stringLiteral = b.literal("asdf");
2188 assert.strictEqual(stringLiteral.regex, null);
2189 n.Literal.assert(stringLiteral, true);
2190
2191 var regExpLiteral = b.literal(/a.b/gi);
2192 assert.strictEqual(regExpLiteral.regex.pattern, "a.b");
2193 assert.strictEqual(regExpLiteral.regex.flags, "ig");
2194 n.Literal.assert(regExpLiteral, true);
2195
2196 regExpLiteral.regex.pattern = 1234;
2197 assert.strictEqual(n.Literal.check(regExpLiteral, true), false);
2198 });
2199 });
2200
2256 check("0n");
2257 check("12345n");
2258 check("0b101011101n");
2259 check("0xFFF123n");
2260 check("0xfff123n");
2261 check("728374682736419273912879879610912837401293846n");
2262 check("0xc00cda0a30d6312b54c55789befdea84f5949d92n");
2263 check("0o16432n");
2264 });
2265 });
22012266
22022267 describe("MemberExpression", function() {
2203 it("should set computed flag to false by default", function(){
2204 var memberExpression = b.memberExpression(
2205 b.identifier('foo'),
2206 b.identifier('bar')
2207 )
2208
2209 assert.strictEqual(memberExpression.computed, false)
2210 });
2211
2212 it("should not set computed to true if property is a callExpression", function(){
2213 var memberExpression = b.memberExpression(
2214 b.identifier('foo'),
2215 b.callExpression(b.identifier('bar'), [])
2216 )
2217
2218 assert.strictEqual(memberExpression.computed, false)
2219 });
2220
2221 it("should set computed flag to true if property is a literal", function(){
2222 var memberExpression = b.memberExpression(
2223 b.identifier('foo'),
2224 b.literal('bar')
2225 )
2226
2227 assert.strictEqual(memberExpression.computed, true)
2228 });
2229
2230 it("should set computed flag to true if property is a memberExpression", function(){
2231 var memberExpression = b.memberExpression(
2232 b.identifier('foo'),
2233 b.memberExpression(b.identifier('foo'), b.literal('bar'))
2234 )
2235
2236 assert.strictEqual(memberExpression.computed, true)
2237 });
2238
2239 it("should set computed flag to true if property is a binaryExpression", function(){
2240 var memberExpression = b.memberExpression(
2241 b.identifier('foo'),
2242 b.memberExpression(b.identifier('foo'), b.literal('bar'))
2243 )
2244
2245 assert.strictEqual(memberExpression.computed, true)
2246 });
2247
2248 it("should override computed value when passed as a third argument to the builder", function(){
2249 var memberExpression = b.memberExpression(
2250 b.identifier('foo'),
2251 b.callExpression(b.identifier('bar'), []),
2252 true
2253 )
2254
2255 assert.strictEqual(memberExpression.computed, true);
2256 });
2257 });
2268 it("should set computed flag to false by default", function(){
2269 var memberExpression = b.memberExpression(
2270 b.identifier('foo'),
2271 b.identifier('bar')
2272 )
2273
2274 assert.strictEqual(memberExpression.computed, false)
2275 });
2276
2277 it("should not set computed to true if property is a callExpression", function(){
2278 var memberExpression = b.memberExpression(
2279 b.identifier('foo'),
2280 b.callExpression(b.identifier('bar'), [])
2281 )
2282
2283 assert.strictEqual(memberExpression.computed, false)
2284 });
2285
2286 it("should set computed flag to true if property is a literal", function(){
2287 var memberExpression = b.memberExpression(
2288 b.identifier('foo'),
2289 b.literal('bar')
2290 )
2291
2292 assert.strictEqual(memberExpression.computed, true)
2293 });
2294
2295 it("should set computed flag to true if property is a memberExpression", function(){
2296 var memberExpression = b.memberExpression(
2297 b.identifier('foo'),
2298 b.memberExpression(b.identifier('foo'), b.literal('bar'))
2299 )
2300
2301 assert.strictEqual(memberExpression.computed, true)
2302 });
2303
2304 it("should set computed flag to true if property is a binaryExpression", function(){
2305 var memberExpression = b.memberExpression(
2306 b.identifier('foo'),
2307 b.memberExpression(b.identifier('foo'), b.literal('bar'))
2308 )
2309
2310 assert.strictEqual(memberExpression.computed, true)
2311 });
2312
2313 it("should override computed value when passed as a third argument to the builder", function(){
2314 var memberExpression = b.memberExpression(
2315 b.identifier('foo'),
2316 b.callExpression(b.identifier('bar'), []),
2317 true
2318 )
2319
2320 assert.strictEqual(memberExpression.computed, true);
2321 });
2322 });