ast-types 0.8.11 → 0.8.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.travis.yml +6 -1
- package/def/core.js +9 -1
- package/def/fb-harmony.js +21 -1
- package/lib/equiv.js +12 -6
- package/lib/node-path.js +38 -13
- package/lib/path-visitor.js +76 -31
- package/lib/path.js +34 -16
- package/lib/scope.js +62 -18
- package/lib/types.js +72 -38
- package/package.json +1 -1
package/.travis.yml
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
language: node_js
|
|
2
2
|
node_js:
|
|
3
|
+
- "4.0"
|
|
4
|
+
- "iojs"
|
|
3
5
|
- "0.12"
|
|
4
6
|
- "0.11"
|
|
5
7
|
- "0.10"
|
|
6
8
|
- "0.8"
|
|
7
9
|
- "0.6"
|
|
10
|
+
|
|
11
|
+
sudo: false
|
|
8
12
|
|
|
9
13
|
before_install:
|
|
10
14
|
npm install -g npm@'>=1.4.3'
|
|
11
15
|
|
|
12
16
|
matrix:
|
|
13
17
|
allow_failures:
|
|
14
|
-
- node_js: "0.
|
|
18
|
+
- node_js: "0.8"
|
|
19
|
+
- node_js: "0.6"
|
package/def/core.js
CHANGED
|
@@ -305,7 +305,15 @@ def("MemberExpression")
|
|
|
305
305
|
.build("object", "property", "computed")
|
|
306
306
|
.field("object", def("Expression"))
|
|
307
307
|
.field("property", or(def("Identifier"), def("Expression")))
|
|
308
|
-
.field("computed", Boolean,
|
|
308
|
+
.field("computed", Boolean, function(){
|
|
309
|
+
var type = this.property.type;
|
|
310
|
+
if (type === 'Literal' ||
|
|
311
|
+
type === 'MemberExpression' ||
|
|
312
|
+
type === 'BinaryExpression') {
|
|
313
|
+
return true;
|
|
314
|
+
}
|
|
315
|
+
return false;
|
|
316
|
+
});
|
|
309
317
|
|
|
310
318
|
def("Pattern").bases("Node");
|
|
311
319
|
|
package/def/fb-harmony.js
CHANGED
|
@@ -289,7 +289,7 @@ def("InterfaceExtends")
|
|
|
289
289
|
.field("typeParameters", or(def("TypeParameterInstantiation"), null));
|
|
290
290
|
|
|
291
291
|
def("TypeAlias")
|
|
292
|
-
.bases("
|
|
292
|
+
.bases("Declaration")
|
|
293
293
|
.build("id", "typeParameters", "right")
|
|
294
294
|
.field("id", def("Identifier"))
|
|
295
295
|
.field("typeParameters", or(def("TypeParameterDeclaration"), null))
|
|
@@ -325,3 +325,23 @@ def("DeclareModule")
|
|
|
325
325
|
.build("id", "body")
|
|
326
326
|
.field("id", or(def("Identifier"), def("Literal")))
|
|
327
327
|
.field("body", def("BlockStatement"));
|
|
328
|
+
|
|
329
|
+
def("DeclareExportDeclaration")
|
|
330
|
+
.bases("Declaration")
|
|
331
|
+
.build("default", "declaration", "specifiers", "source")
|
|
332
|
+
.field("default", Boolean)
|
|
333
|
+
.field("declaration", or(
|
|
334
|
+
def("DeclareVariable"),
|
|
335
|
+
def("DeclareFunction"),
|
|
336
|
+
def("DeclareClass"),
|
|
337
|
+
def("Type"), // Implies default.
|
|
338
|
+
null
|
|
339
|
+
))
|
|
340
|
+
.field("specifiers", [or(
|
|
341
|
+
def("ExportSpecifier"),
|
|
342
|
+
def("ExportBatchSpecifier")
|
|
343
|
+
)], defaults.emptyArray)
|
|
344
|
+
.field("source", or(
|
|
345
|
+
def("Literal"),
|
|
346
|
+
null
|
|
347
|
+
), defaults["null"]);
|
package/lib/equiv.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
var assert = require("assert");
|
|
2
1
|
var types = require("../main");
|
|
3
2
|
var getFieldNames = types.getFieldNames;
|
|
4
3
|
var getFieldValue = types.getFieldValue;
|
|
@@ -22,10 +21,11 @@ astNodesAreEquivalent.assert = function(a, b) {
|
|
|
22
21
|
var problemPath = [];
|
|
23
22
|
if (!astNodesAreEquivalent(a, b, problemPath)) {
|
|
24
23
|
if (problemPath.length === 0) {
|
|
25
|
-
|
|
24
|
+
if (a !== b) {
|
|
25
|
+
throw new Error("Nodes must be equal");
|
|
26
|
+
}
|
|
26
27
|
} else {
|
|
27
|
-
|
|
28
|
-
false,
|
|
28
|
+
throw new Error(
|
|
29
29
|
"Nodes differ in the following path: " +
|
|
30
30
|
problemPath.map(subscriptForProperty).join("")
|
|
31
31
|
);
|
|
@@ -94,7 +94,10 @@ function arraysAreEquivalent(a, b, problemPath) {
|
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
if (problemPath) {
|
|
97
|
-
|
|
97
|
+
var problemPathTail = problemPath.pop();
|
|
98
|
+
if (problemPathTail !== i) {
|
|
99
|
+
throw new Error("" + problemPathTail);
|
|
100
|
+
}
|
|
98
101
|
}
|
|
99
102
|
}
|
|
100
103
|
|
|
@@ -136,7 +139,10 @@ function objectsAreEquivalent(a, b, problemPath) {
|
|
|
136
139
|
}
|
|
137
140
|
|
|
138
141
|
if (problemPath) {
|
|
139
|
-
|
|
142
|
+
var problemPathTail = problemPath.pop();
|
|
143
|
+
if (problemPathTail !== name) {
|
|
144
|
+
throw new Error("" + problemPathTail);
|
|
145
|
+
}
|
|
140
146
|
}
|
|
141
147
|
}
|
|
142
148
|
|
package/lib/node-path.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
var assert = require("assert");
|
|
2
1
|
var types = require("./types");
|
|
3
2
|
var n = types.namedTypes;
|
|
4
3
|
var b = types.builders;
|
|
@@ -8,12 +7,20 @@ var Path = require("./path");
|
|
|
8
7
|
var Scope = require("./scope");
|
|
9
8
|
|
|
10
9
|
function NodePath(value, parentPath, name) {
|
|
11
|
-
|
|
10
|
+
if (!(this instanceof NodePath)) {
|
|
11
|
+
throw new Error("NodePath constructor cannot be invoked without 'new'");
|
|
12
|
+
}
|
|
12
13
|
Path.call(this, value, parentPath, name);
|
|
13
14
|
}
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
var NPp = NodePath.prototype = Object.create(Path.prototype, {
|
|
17
|
+
constructor: {
|
|
18
|
+
value: NodePath,
|
|
19
|
+
enumerable: false,
|
|
20
|
+
writable: true,
|
|
21
|
+
configurable: true
|
|
22
|
+
}
|
|
23
|
+
});
|
|
17
24
|
|
|
18
25
|
Object.defineProperties(NPp, {
|
|
19
26
|
node: {
|
|
@@ -192,7 +199,9 @@ NPp.needsParens = function(assumeExpressionContext) {
|
|
|
192
199
|
}
|
|
193
200
|
|
|
194
201
|
if (pp === np && this.name === "right") {
|
|
195
|
-
|
|
202
|
+
if (parent.right !== node) {
|
|
203
|
+
throw new Error("Nodes must be equal");
|
|
204
|
+
}
|
|
196
205
|
return true;
|
|
197
206
|
}
|
|
198
207
|
|
|
@@ -350,51 +359,67 @@ function firstInStatement(path) {
|
|
|
350
359
|
if (n.BlockStatement.check(parent) &&
|
|
351
360
|
path.parent.name === "body" &&
|
|
352
361
|
path.name === 0) {
|
|
353
|
-
|
|
362
|
+
if (parent.body[0] !== node) {
|
|
363
|
+
throw new Error("Nodes must be equal");
|
|
364
|
+
}
|
|
354
365
|
return true;
|
|
355
366
|
}
|
|
356
367
|
|
|
357
368
|
if (n.ExpressionStatement.check(parent) &&
|
|
358
369
|
path.name === "expression") {
|
|
359
|
-
|
|
370
|
+
if (parent.expression !== node) {
|
|
371
|
+
throw new Error("Nodes must be equal");
|
|
372
|
+
}
|
|
360
373
|
return true;
|
|
361
374
|
}
|
|
362
375
|
|
|
363
376
|
if (n.SequenceExpression.check(parent) &&
|
|
364
377
|
path.parent.name === "expressions" &&
|
|
365
378
|
path.name === 0) {
|
|
366
|
-
|
|
379
|
+
if (parent.expressions[0] !== node) {
|
|
380
|
+
throw new Error("Nodes must be equal");
|
|
381
|
+
}
|
|
367
382
|
continue;
|
|
368
383
|
}
|
|
369
384
|
|
|
370
385
|
if (n.CallExpression.check(parent) &&
|
|
371
386
|
path.name === "callee") {
|
|
372
|
-
|
|
387
|
+
if (parent.callee !== node) {
|
|
388
|
+
throw new Error("Nodes must be equal");
|
|
389
|
+
}
|
|
373
390
|
continue;
|
|
374
391
|
}
|
|
375
392
|
|
|
376
393
|
if (n.MemberExpression.check(parent) &&
|
|
377
394
|
path.name === "object") {
|
|
378
|
-
|
|
395
|
+
if (parent.object !== node) {
|
|
396
|
+
throw new Error("Nodes must be equal");
|
|
397
|
+
}
|
|
379
398
|
continue;
|
|
380
399
|
}
|
|
381
400
|
|
|
382
401
|
if (n.ConditionalExpression.check(parent) &&
|
|
383
402
|
path.name === "test") {
|
|
384
|
-
|
|
403
|
+
if (parent.test !== node) {
|
|
404
|
+
throw new Error("Nodes must be equal");
|
|
405
|
+
}
|
|
385
406
|
continue;
|
|
386
407
|
}
|
|
387
408
|
|
|
388
409
|
if (isBinary(parent) &&
|
|
389
410
|
path.name === "left") {
|
|
390
|
-
|
|
411
|
+
if (parent.left !== node) {
|
|
412
|
+
throw new Error("Nodes must be equal");
|
|
413
|
+
}
|
|
391
414
|
continue;
|
|
392
415
|
}
|
|
393
416
|
|
|
394
417
|
if (n.UnaryExpression.check(parent) &&
|
|
395
418
|
!parent.prefix &&
|
|
396
419
|
path.name === "argument") {
|
|
397
|
-
|
|
420
|
+
if (parent.argument !== node) {
|
|
421
|
+
throw new Error("Nodes must be equal");
|
|
422
|
+
}
|
|
398
423
|
continue;
|
|
399
424
|
}
|
|
400
425
|
|
package/lib/path-visitor.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
var assert = require("assert");
|
|
2
1
|
var types = require("./types");
|
|
3
2
|
var NodePath = require("./node-path");
|
|
4
3
|
var Printable = types.namedTypes.Printable;
|
|
@@ -9,7 +8,11 @@ var hasOwn = Object.prototype.hasOwnProperty;
|
|
|
9
8
|
var undefined;
|
|
10
9
|
|
|
11
10
|
function PathVisitor() {
|
|
12
|
-
|
|
11
|
+
if (!(this instanceof PathVisitor)) {
|
|
12
|
+
throw new Error(
|
|
13
|
+
"PathVisitor constructor cannot be invoked without 'new'"
|
|
14
|
+
);
|
|
15
|
+
}
|
|
13
16
|
|
|
14
17
|
// Permanent state.
|
|
15
18
|
this._reusableContextStack = [];
|
|
@@ -62,7 +65,11 @@ PathVisitor.fromMethodsObject = function fromMethodsObject(methods) {
|
|
|
62
65
|
}
|
|
63
66
|
|
|
64
67
|
function Visitor() {
|
|
65
|
-
|
|
68
|
+
if (!(this instanceof Visitor)) {
|
|
69
|
+
throw new Error(
|
|
70
|
+
"Visitor constructor cannot be invoked without 'new'"
|
|
71
|
+
);
|
|
72
|
+
}
|
|
66
73
|
PathVisitor.call(this);
|
|
67
74
|
}
|
|
68
75
|
|
|
@@ -94,13 +101,13 @@ PathVisitor.visit = function visit(node, methods) {
|
|
|
94
101
|
|
|
95
102
|
var PVp = PathVisitor.prototype;
|
|
96
103
|
|
|
97
|
-
var recursiveVisitWarning = [
|
|
98
|
-
"Recursively calling visitor.visit(path) resets visitor state.",
|
|
99
|
-
"Try this.visit(path) or this.traverse(path) instead."
|
|
100
|
-
].join(" ");
|
|
101
|
-
|
|
102
104
|
PVp.visit = function() {
|
|
103
|
-
|
|
105
|
+
if (this._visiting) {
|
|
106
|
+
throw new Error(
|
|
107
|
+
"Recursively calling visitor.visit(path) resets visitor state. " +
|
|
108
|
+
"Try this.visit(path) or this.traverse(path) instead."
|
|
109
|
+
);
|
|
110
|
+
}
|
|
104
111
|
|
|
105
112
|
// Private state that needs to be reset before every traversal.
|
|
106
113
|
this._visiting = true;
|
|
@@ -170,7 +177,10 @@ PVp.visitWithoutReset = function(path) {
|
|
|
170
177
|
return this.visitor.visitWithoutReset(path);
|
|
171
178
|
}
|
|
172
179
|
|
|
173
|
-
|
|
180
|
+
if (!(path instanceof NodePath)) {
|
|
181
|
+
throw new Error("");
|
|
182
|
+
}
|
|
183
|
+
|
|
174
184
|
var value = path.value;
|
|
175
185
|
|
|
176
186
|
var methodName = value &&
|
|
@@ -194,8 +204,12 @@ PVp.visitWithoutReset = function(path) {
|
|
|
194
204
|
};
|
|
195
205
|
|
|
196
206
|
function visitChildren(path, visitor) {
|
|
197
|
-
|
|
198
|
-
|
|
207
|
+
if (!(path instanceof NodePath)) {
|
|
208
|
+
throw new Error("");
|
|
209
|
+
}
|
|
210
|
+
if (!(visitor instanceof PathVisitor)) {
|
|
211
|
+
throw new Error("");
|
|
212
|
+
}
|
|
199
213
|
|
|
200
214
|
var value = path.value;
|
|
201
215
|
|
|
@@ -242,7 +256,9 @@ PVp.acquireContext = function(path) {
|
|
|
242
256
|
};
|
|
243
257
|
|
|
244
258
|
PVp.releaseContext = function(context) {
|
|
245
|
-
|
|
259
|
+
if (!(context instanceof this.Context)) {
|
|
260
|
+
throw new Error("");
|
|
261
|
+
}
|
|
246
262
|
this._reusableContextStack.push(context);
|
|
247
263
|
context.currentPath = null;
|
|
248
264
|
};
|
|
@@ -257,9 +273,15 @@ PVp.wasChangeReported = function() {
|
|
|
257
273
|
|
|
258
274
|
function makeContextConstructor(visitor) {
|
|
259
275
|
function Context(path) {
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
276
|
+
if (!(this instanceof Context)) {
|
|
277
|
+
throw new Error("");
|
|
278
|
+
}
|
|
279
|
+
if (!(this instanceof PathVisitor)) {
|
|
280
|
+
throw new Error("");
|
|
281
|
+
}
|
|
282
|
+
if (!(path instanceof NodePath)) {
|
|
283
|
+
throw new Error("");
|
|
284
|
+
}
|
|
263
285
|
|
|
264
286
|
Object.defineProperty(this, "visitor", {
|
|
265
287
|
value: visitor,
|
|
@@ -274,7 +296,9 @@ function makeContextConstructor(visitor) {
|
|
|
274
296
|
Object.seal(this);
|
|
275
297
|
}
|
|
276
298
|
|
|
277
|
-
|
|
299
|
+
if (!(visitor instanceof PathVisitor)) {
|
|
300
|
+
throw new Error("");
|
|
301
|
+
}
|
|
278
302
|
|
|
279
303
|
// Note that the visitor object is the prototype of Context.prototype,
|
|
280
304
|
// so all visitor methods are inherited by context objects.
|
|
@@ -293,8 +317,12 @@ var sharedContextProtoMethods = Object.create(null);
|
|
|
293
317
|
|
|
294
318
|
sharedContextProtoMethods.reset =
|
|
295
319
|
function reset(path) {
|
|
296
|
-
|
|
297
|
-
|
|
320
|
+
if (!(this instanceof this.Context)) {
|
|
321
|
+
throw new Error("");
|
|
322
|
+
}
|
|
323
|
+
if (!(path instanceof NodePath)) {
|
|
324
|
+
throw new Error("");
|
|
325
|
+
}
|
|
298
326
|
|
|
299
327
|
this.currentPath = path;
|
|
300
328
|
this.needToCallTraverse = true;
|
|
@@ -304,8 +332,12 @@ function reset(path) {
|
|
|
304
332
|
|
|
305
333
|
sharedContextProtoMethods.invokeVisitorMethod =
|
|
306
334
|
function invokeVisitorMethod(methodName) {
|
|
307
|
-
|
|
308
|
-
|
|
335
|
+
if (!(this instanceof this.Context)) {
|
|
336
|
+
throw new Error("");
|
|
337
|
+
}
|
|
338
|
+
if (!(this.currentPath instanceof NodePath)) {
|
|
339
|
+
throw new Error("");
|
|
340
|
+
}
|
|
309
341
|
|
|
310
342
|
var result = this.visitor[methodName].call(this, this.currentPath);
|
|
311
343
|
|
|
@@ -327,10 +359,11 @@ function invokeVisitorMethod(methodName) {
|
|
|
327
359
|
}
|
|
328
360
|
}
|
|
329
361
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
362
|
+
if (this.needToCallTraverse !== false) {
|
|
363
|
+
throw new Error(
|
|
364
|
+
"Must either call this.traverse or return false in " + methodName
|
|
365
|
+
);
|
|
366
|
+
}
|
|
334
367
|
|
|
335
368
|
var path = this.currentPath;
|
|
336
369
|
return path && path.value;
|
|
@@ -338,9 +371,15 @@ function invokeVisitorMethod(methodName) {
|
|
|
338
371
|
|
|
339
372
|
sharedContextProtoMethods.traverse =
|
|
340
373
|
function traverse(path, newVisitor) {
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
374
|
+
if (!(this instanceof this.Context)) {
|
|
375
|
+
throw new Error("");
|
|
376
|
+
}
|
|
377
|
+
if (!(path instanceof NodePath)) {
|
|
378
|
+
throw new Error("");
|
|
379
|
+
}
|
|
380
|
+
if (!(this.currentPath instanceof NodePath)) {
|
|
381
|
+
throw new Error("");
|
|
382
|
+
}
|
|
344
383
|
|
|
345
384
|
this.needToCallTraverse = false;
|
|
346
385
|
|
|
@@ -351,9 +390,15 @@ function traverse(path, newVisitor) {
|
|
|
351
390
|
|
|
352
391
|
sharedContextProtoMethods.visit =
|
|
353
392
|
function visit(path, newVisitor) {
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
393
|
+
if (!(this instanceof this.Context)) {
|
|
394
|
+
throw new Error("");
|
|
395
|
+
}
|
|
396
|
+
if (!(path instanceof NodePath)) {
|
|
397
|
+
throw new Error("");
|
|
398
|
+
}
|
|
399
|
+
if (!(this.currentPath instanceof NodePath)) {
|
|
400
|
+
throw new Error("");
|
|
401
|
+
}
|
|
357
402
|
|
|
358
403
|
this.needToCallTraverse = false;
|
|
359
404
|
|
package/lib/path.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
var assert = require("assert");
|
|
2
1
|
var Op = Object.prototype;
|
|
3
2
|
var hasOwn = Op.hasOwnProperty;
|
|
4
3
|
var types = require("./types");
|
|
@@ -9,10 +8,14 @@ var slice = Ap.slice;
|
|
|
9
8
|
var map = Ap.map;
|
|
10
9
|
|
|
11
10
|
function Path(value, parentPath, name) {
|
|
12
|
-
|
|
11
|
+
if (!(this instanceof Path)) {
|
|
12
|
+
throw new Error("Path constructor cannot be invoked without 'new'");
|
|
13
|
+
}
|
|
13
14
|
|
|
14
15
|
if (parentPath) {
|
|
15
|
-
|
|
16
|
+
if (!(parentPath instanceof Path)) {
|
|
17
|
+
throw new Error("");
|
|
18
|
+
}
|
|
16
19
|
} else {
|
|
17
20
|
parentPath = null;
|
|
18
21
|
name = null;
|
|
@@ -154,7 +157,9 @@ function getMoves(path, offset, start, end) {
|
|
|
154
157
|
for (var i = start; i < end; ++i) {
|
|
155
158
|
if (hasOwn.call(path.value, i)) {
|
|
156
159
|
var childPath = path.get(i);
|
|
157
|
-
|
|
160
|
+
if (childPath.name !== i) {
|
|
161
|
+
throw new Error("");
|
|
162
|
+
}
|
|
158
163
|
var newIndex = i + offset;
|
|
159
164
|
childPath.name = newIndex;
|
|
160
165
|
moves[newIndex] = childPath;
|
|
@@ -167,7 +172,9 @@ function getMoves(path, offset, start, end) {
|
|
|
167
172
|
return function() {
|
|
168
173
|
for (var newIndex in moves) {
|
|
169
174
|
var childPath = moves[newIndex];
|
|
170
|
-
|
|
175
|
+
if (childPath.name !== +newIndex) {
|
|
176
|
+
throw new Error("");
|
|
177
|
+
}
|
|
171
178
|
cache[newIndex] = childPath;
|
|
172
179
|
path.value[newIndex] = childPath.value;
|
|
173
180
|
}
|
|
@@ -241,7 +248,9 @@ Pp.insertAfter = function insertAfter(node) {
|
|
|
241
248
|
};
|
|
242
249
|
|
|
243
250
|
function repairRelationshipWithParent(path) {
|
|
244
|
-
|
|
251
|
+
if (!(path instanceof Path)) {
|
|
252
|
+
throw new Error("");
|
|
253
|
+
}
|
|
245
254
|
|
|
246
255
|
var pp = path.parentPath;
|
|
247
256
|
if (!pp) {
|
|
@@ -270,8 +279,12 @@ function repairRelationshipWithParent(path) {
|
|
|
270
279
|
parentCache[path.name] = path;
|
|
271
280
|
}
|
|
272
281
|
|
|
273
|
-
|
|
274
|
-
|
|
282
|
+
if (parentValue[path.name] !== path.value) {
|
|
283
|
+
throw new Error("");
|
|
284
|
+
}
|
|
285
|
+
if (path.parentPath.get(path.name) !== path) {
|
|
286
|
+
throw new Error("");
|
|
287
|
+
}
|
|
275
288
|
|
|
276
289
|
return path;
|
|
277
290
|
}
|
|
@@ -295,11 +308,12 @@ Pp.replace = function replace(replacement) {
|
|
|
295
308
|
|
|
296
309
|
var splicedOut = parentValue.splice.apply(parentValue, spliceArgs);
|
|
297
310
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
311
|
+
if (splicedOut[0] !== this.value) {
|
|
312
|
+
throw new Error("");
|
|
313
|
+
}
|
|
314
|
+
if (parentValue.length !== (originalLength - 1 + count)) {
|
|
315
|
+
throw new Error("");
|
|
316
|
+
}
|
|
303
317
|
|
|
304
318
|
move();
|
|
305
319
|
|
|
@@ -309,7 +323,9 @@ Pp.replace = function replace(replacement) {
|
|
|
309
323
|
this.__childCache = null;
|
|
310
324
|
|
|
311
325
|
} else {
|
|
312
|
-
|
|
326
|
+
if (parentValue[this.name] !== replacement) {
|
|
327
|
+
throw new Error("");
|
|
328
|
+
}
|
|
313
329
|
|
|
314
330
|
if (this.value !== replacement) {
|
|
315
331
|
this.value = replacement;
|
|
@@ -320,7 +336,9 @@ Pp.replace = function replace(replacement) {
|
|
|
320
336
|
results.push(this.parentPath.get(this.name + i));
|
|
321
337
|
}
|
|
322
338
|
|
|
323
|
-
|
|
339
|
+
if (results[0] !== this) {
|
|
340
|
+
throw new Error("");
|
|
341
|
+
}
|
|
324
342
|
}
|
|
325
343
|
|
|
326
344
|
} else if (count === 1) {
|
|
@@ -339,7 +357,7 @@ Pp.replace = function replace(replacement) {
|
|
|
339
357
|
// it no longer has a value defined.
|
|
340
358
|
|
|
341
359
|
} else {
|
|
342
|
-
|
|
360
|
+
throw new Error("Could not replace path");
|
|
343
361
|
}
|
|
344
362
|
|
|
345
363
|
return results;
|
package/lib/scope.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
var assert = require("assert");
|
|
2
1
|
var types = require("./types");
|
|
3
2
|
var Type = types.Type;
|
|
4
3
|
var namedTypes = types.namedTypes;
|
|
@@ -9,14 +8,20 @@ var hasOwn = Object.prototype.hasOwnProperty;
|
|
|
9
8
|
var b = types.builders;
|
|
10
9
|
|
|
11
10
|
function Scope(path, parentScope) {
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
if (!(this instanceof Scope)) {
|
|
12
|
+
throw new Error("Scope constructor cannot be invoked without 'new'");
|
|
13
|
+
}
|
|
14
|
+
if (!(path instanceof require("./node-path"))) {
|
|
15
|
+
throw new Error("");
|
|
16
|
+
}
|
|
14
17
|
ScopeType.assert(path.value);
|
|
15
18
|
|
|
16
19
|
var depth;
|
|
17
20
|
|
|
18
21
|
if (parentScope) {
|
|
19
|
-
|
|
22
|
+
if (!(parentScope instanceof Scope)) {
|
|
23
|
+
throw new Error("");
|
|
24
|
+
}
|
|
20
25
|
depth = parentScope.depth + 1;
|
|
21
26
|
} else {
|
|
22
27
|
parentScope = null;
|
|
@@ -29,7 +34,8 @@ function Scope(path, parentScope) {
|
|
|
29
34
|
isGlobal: { value: !parentScope, enumerable: true },
|
|
30
35
|
depth: { value: depth },
|
|
31
36
|
parent: { value: parentScope },
|
|
32
|
-
bindings: { value: {} }
|
|
37
|
+
bindings: { value: {} },
|
|
38
|
+
types: { value: {} },
|
|
33
39
|
});
|
|
34
40
|
}
|
|
35
41
|
|
|
@@ -62,9 +68,16 @@ Sp.declares = function(name) {
|
|
|
62
68
|
return hasOwn.call(this.bindings, name);
|
|
63
69
|
};
|
|
64
70
|
|
|
71
|
+
Sp.declaresType = function(name) {
|
|
72
|
+
this.scan();
|
|
73
|
+
return hasOwn.call(this.types, name);
|
|
74
|
+
};
|
|
75
|
+
|
|
65
76
|
Sp.declareTemporary = function(prefix) {
|
|
66
77
|
if (prefix) {
|
|
67
|
-
|
|
78
|
+
if (!/^[a-z$_]/i.test(prefix)) {
|
|
79
|
+
throw new Error("");
|
|
80
|
+
}
|
|
68
81
|
} else {
|
|
69
82
|
prefix = "t$";
|
|
70
83
|
}
|
|
@@ -108,7 +121,7 @@ Sp.scan = function(force) {
|
|
|
108
121
|
// Empty out this.bindings, just in cases.
|
|
109
122
|
delete this.bindings[name];
|
|
110
123
|
}
|
|
111
|
-
scanScope(this.path, this.bindings);
|
|
124
|
+
scanScope(this.path, this.bindings, this.types);
|
|
112
125
|
this.didScan = true;
|
|
113
126
|
}
|
|
114
127
|
};
|
|
@@ -118,7 +131,12 @@ Sp.getBindings = function () {
|
|
|
118
131
|
return this.bindings;
|
|
119
132
|
};
|
|
120
133
|
|
|
121
|
-
function
|
|
134
|
+
Sp.getTypes = function () {
|
|
135
|
+
this.scan();
|
|
136
|
+
return this.types;
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
function scanScope(path, bindings, scopeTypes) {
|
|
122
140
|
var node = path.value;
|
|
123
141
|
ScopeType.assert(node);
|
|
124
142
|
|
|
@@ -129,11 +147,11 @@ function scanScope(path, bindings) {
|
|
|
129
147
|
addPattern(path.get("param"), bindings);
|
|
130
148
|
|
|
131
149
|
} else {
|
|
132
|
-
recursiveScanScope(path, bindings);
|
|
150
|
+
recursiveScanScope(path, bindings, scopeTypes);
|
|
133
151
|
}
|
|
134
152
|
}
|
|
135
153
|
|
|
136
|
-
function recursiveScanScope(path, bindings) {
|
|
154
|
+
function recursiveScanScope(path, bindings, scopeTypes) {
|
|
137
155
|
var node = path.value;
|
|
138
156
|
|
|
139
157
|
if (path.parent &&
|
|
@@ -147,7 +165,7 @@ function recursiveScanScope(path, bindings) {
|
|
|
147
165
|
|
|
148
166
|
} else if (isArray.check(node)) {
|
|
149
167
|
path.each(function(childPath) {
|
|
150
|
-
recursiveScanChild(childPath, bindings);
|
|
168
|
+
recursiveScanChild(childPath, bindings, scopeTypes);
|
|
151
169
|
});
|
|
152
170
|
|
|
153
171
|
} else if (namedTypes.Function.check(node)) {
|
|
@@ -155,11 +173,14 @@ function recursiveScanScope(path, bindings) {
|
|
|
155
173
|
addPattern(paramPath, bindings);
|
|
156
174
|
});
|
|
157
175
|
|
|
158
|
-
recursiveScanChild(path.get("body"), bindings);
|
|
176
|
+
recursiveScanChild(path.get("body"), bindings, scopeTypes);
|
|
177
|
+
|
|
178
|
+
} else if (namedTypes.TypeAlias && namedTypes.TypeAlias.check(node)) {
|
|
179
|
+
addTypePattern(path.get("id"), scopeTypes);
|
|
159
180
|
|
|
160
181
|
} else if (namedTypes.VariableDeclarator.check(node)) {
|
|
161
182
|
addPattern(path.get("id"), bindings);
|
|
162
|
-
recursiveScanChild(path.get("init"), bindings);
|
|
183
|
+
recursiveScanChild(path.get("init"), bindings, scopeTypes);
|
|
163
184
|
|
|
164
185
|
} else if (node.type === "ImportSpecifier" ||
|
|
165
186
|
node.type === "ImportNamespaceSpecifier" ||
|
|
@@ -177,13 +198,15 @@ function recursiveScanScope(path, bindings) {
|
|
|
177
198
|
} else if (Node.check(node) && !Expression.check(node)) {
|
|
178
199
|
types.eachField(node, function(name, child) {
|
|
179
200
|
var childPath = path.get(name);
|
|
180
|
-
|
|
181
|
-
|
|
201
|
+
if (childPath.value !== child) {
|
|
202
|
+
throw new Error("");
|
|
203
|
+
}
|
|
204
|
+
recursiveScanChild(childPath, bindings, scopeTypes);
|
|
182
205
|
});
|
|
183
206
|
}
|
|
184
207
|
}
|
|
185
208
|
|
|
186
|
-
function recursiveScanChild(path, bindings) {
|
|
209
|
+
function recursiveScanChild(path, bindings, scopeTypes) {
|
|
187
210
|
var node = path.value;
|
|
188
211
|
|
|
189
212
|
if (!node || Expression.check(node)) {
|
|
@@ -204,7 +227,7 @@ function recursiveScanChild(path, bindings) {
|
|
|
204
227
|
// Any declarations that occur inside the catch body that do
|
|
205
228
|
// not have the same name as the catch parameter should count
|
|
206
229
|
// as bindings in the outer scope.
|
|
207
|
-
recursiveScanScope(path.get("body"), bindings);
|
|
230
|
+
recursiveScanScope(path.get("body"), bindings, scopeTypes);
|
|
208
231
|
|
|
209
232
|
// If a new binding matching the catch parameter name was
|
|
210
233
|
// created while scanning the catch body, ignore it because it
|
|
@@ -216,7 +239,7 @@ function recursiveScanChild(path, bindings) {
|
|
|
216
239
|
}
|
|
217
240
|
|
|
218
241
|
} else {
|
|
219
|
-
recursiveScanScope(path, bindings);
|
|
242
|
+
recursiveScanScope(path, bindings, scopeTypes);
|
|
220
243
|
}
|
|
221
244
|
}
|
|
222
245
|
|
|
@@ -269,6 +292,20 @@ function addPattern(patternPath, bindings) {
|
|
|
269
292
|
}
|
|
270
293
|
}
|
|
271
294
|
|
|
295
|
+
function addTypePattern(patternPath, types) {
|
|
296
|
+
var pattern = patternPath.value;
|
|
297
|
+
namedTypes.Pattern.assert(pattern);
|
|
298
|
+
|
|
299
|
+
if (namedTypes.Identifier.check(pattern)) {
|
|
300
|
+
if (hasOwn.call(types, pattern.name)) {
|
|
301
|
+
types[pattern.name].push(patternPath);
|
|
302
|
+
} else {
|
|
303
|
+
types[pattern.name] = [patternPath];
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
272
309
|
Sp.lookup = function(name) {
|
|
273
310
|
for (var scope = this; scope; scope = scope.parent)
|
|
274
311
|
if (scope.declares(name))
|
|
@@ -276,6 +313,13 @@ Sp.lookup = function(name) {
|
|
|
276
313
|
return scope;
|
|
277
314
|
};
|
|
278
315
|
|
|
316
|
+
Sp.lookupType = function(name) {
|
|
317
|
+
for (var scope = this; scope; scope = scope.parent)
|
|
318
|
+
if (scope.declaresType(name))
|
|
319
|
+
break;
|
|
320
|
+
return scope;
|
|
321
|
+
};
|
|
322
|
+
|
|
279
323
|
Sp.getGlobalScope = function() {
|
|
280
324
|
var scope = this;
|
|
281
325
|
while (!scope.isGlobal)
|
package/lib/types.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
var assert = require("assert");
|
|
2
1
|
var Ap = Array.prototype;
|
|
3
2
|
var slice = Ap.slice;
|
|
4
3
|
var map = Ap.map;
|
|
@@ -14,18 +13,22 @@ var hasOwn = Op.hasOwnProperty;
|
|
|
14
13
|
|
|
15
14
|
function Type(check, name) {
|
|
16
15
|
var self = this;
|
|
17
|
-
|
|
16
|
+
if (!(self instanceof Type)) {
|
|
17
|
+
throw new Error("Type constructor cannot be invoked without 'new'");
|
|
18
|
+
}
|
|
18
19
|
|
|
19
20
|
// Unfortunately we can't elegantly reuse isFunction and isString,
|
|
20
21
|
// here, because this code is executed while defining those types.
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
if (objToStr.call(check) !== funObjStr) {
|
|
23
|
+
throw new Error(check + " is not a function");
|
|
24
|
+
}
|
|
23
25
|
|
|
24
26
|
// The `name` parameter can be either a function or a string.
|
|
25
27
|
var nameObjStr = objToStr.call(name);
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
if (!(nameObjStr === funObjStr ||
|
|
29
|
+
nameObjStr === strObjStr)) {
|
|
30
|
+
throw new Error(name + " is neither a function nor a string");
|
|
31
|
+
}
|
|
29
32
|
|
|
30
33
|
Object.defineProperties(self, {
|
|
31
34
|
name: { value: name },
|
|
@@ -50,8 +53,7 @@ exports.Type = Type;
|
|
|
50
53
|
Tp.assert = function(value, deep) {
|
|
51
54
|
if (!this.check(value, deep)) {
|
|
52
55
|
var str = shallowStringify(value);
|
|
53
|
-
|
|
54
|
-
return false;
|
|
56
|
+
throw new Error(str + " does not match type " + this);
|
|
55
57
|
}
|
|
56
58
|
return true;
|
|
57
59
|
};
|
|
@@ -180,10 +182,12 @@ Type.or = function(/* type1, type2, ... */) {
|
|
|
180
182
|
};
|
|
181
183
|
|
|
182
184
|
Type.fromArray = function(arr) {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
185
|
+
if (!isArray.check(arr)) {
|
|
186
|
+
throw new Error("");
|
|
187
|
+
}
|
|
188
|
+
if (arr.length !== 1) {
|
|
189
|
+
throw new Error("only one element type is permitted for typed arrays");
|
|
190
|
+
}
|
|
187
191
|
return toType(arr[0]).arrayOf();
|
|
188
192
|
};
|
|
189
193
|
|
|
@@ -215,7 +219,9 @@ Type.fromObject = function(obj) {
|
|
|
215
219
|
function Field(name, type, defaultFn, hidden) {
|
|
216
220
|
var self = this;
|
|
217
221
|
|
|
218
|
-
|
|
222
|
+
if (!(self instanceof Field)) {
|
|
223
|
+
throw new Error("Field constructor cannot be invoked without 'new'");
|
|
224
|
+
}
|
|
219
225
|
isString.assert(name);
|
|
220
226
|
|
|
221
227
|
type = toType(type);
|
|
@@ -269,7 +275,9 @@ var defCache = Object.create(null);
|
|
|
269
275
|
|
|
270
276
|
function Def(typeName) {
|
|
271
277
|
var self = this;
|
|
272
|
-
|
|
278
|
+
if (!(self instanceof Def)) {
|
|
279
|
+
throw new Error("Def constructor cannot be invoked without 'new'");
|
|
280
|
+
}
|
|
273
281
|
|
|
274
282
|
Object.defineProperties(self, {
|
|
275
283
|
typeName: { value: typeName },
|
|
@@ -309,20 +317,26 @@ var Dp = Def.prototype;
|
|
|
309
317
|
|
|
310
318
|
Dp.isSupertypeOf = function(that) {
|
|
311
319
|
if (that instanceof Def) {
|
|
312
|
-
|
|
313
|
-
|
|
320
|
+
if (this.finalized !== true ||
|
|
321
|
+
that.finalized !== true) {
|
|
322
|
+
throw new Error("");
|
|
323
|
+
}
|
|
314
324
|
return hasOwn.call(that.allSupertypes, this.typeName);
|
|
315
325
|
} else {
|
|
316
|
-
|
|
326
|
+
throw new Error(that + " is not a Def");
|
|
317
327
|
}
|
|
318
328
|
};
|
|
319
329
|
|
|
320
330
|
// Note that the list returned by this function is a copy of the internal
|
|
321
331
|
// supertypeList, *without* the typeName itself as the first element.
|
|
322
332
|
exports.getSupertypeNames = function(typeName) {
|
|
323
|
-
|
|
333
|
+
if (!hasOwn.call(defCache, typeName)) {
|
|
334
|
+
throw new Error("");
|
|
335
|
+
}
|
|
324
336
|
var d = defCache[typeName];
|
|
325
|
-
|
|
337
|
+
if (d.finalized !== true) {
|
|
338
|
+
throw new Error("");
|
|
339
|
+
}
|
|
326
340
|
return d.supertypeList.slice(1);
|
|
327
341
|
};
|
|
328
342
|
|
|
@@ -337,7 +351,9 @@ exports.computeSupertypeLookupTable = function(candidates) {
|
|
|
337
351
|
for (var i = 0; i < typeNameCount; ++i) {
|
|
338
352
|
var typeName = typeNames[i];
|
|
339
353
|
var d = defCache[typeName];
|
|
340
|
-
|
|
354
|
+
if (d.finalized !== true) {
|
|
355
|
+
throw new Error("" + typeName);
|
|
356
|
+
}
|
|
341
357
|
for (var j = 0; j < d.supertypeList.length; ++j) {
|
|
342
358
|
var superTypeName = d.supertypeList[j];
|
|
343
359
|
if (hasOwn.call(candidates, superTypeName)) {
|
|
@@ -352,7 +368,9 @@ exports.computeSupertypeLookupTable = function(candidates) {
|
|
|
352
368
|
|
|
353
369
|
Dp.checkAllFields = function(value, deep) {
|
|
354
370
|
var allFields = this.allFields;
|
|
355
|
-
|
|
371
|
+
if (this.finalized !== true) {
|
|
372
|
+
throw new Error("" + this.typeName);
|
|
373
|
+
}
|
|
356
374
|
|
|
357
375
|
function checkFieldByName(name) {
|
|
358
376
|
var field = allFields[name];
|
|
@@ -366,9 +384,11 @@ Dp.checkAllFields = function(value, deep) {
|
|
|
366
384
|
};
|
|
367
385
|
|
|
368
386
|
Dp.check = function(value, deep) {
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
387
|
+
if (this.finalized !== true) {
|
|
388
|
+
throw new Error(
|
|
389
|
+
"prematurely checking unfinalized type " + this.typeName
|
|
390
|
+
);
|
|
391
|
+
}
|
|
372
392
|
|
|
373
393
|
// A Def type can only match an object value.
|
|
374
394
|
if (!isObject.check(value))
|
|
@@ -420,7 +440,14 @@ Dp.bases = function() {
|
|
|
420
440
|
var bases = this.baseNames;
|
|
421
441
|
|
|
422
442
|
if (this.finalized) {
|
|
423
|
-
|
|
443
|
+
if (args.length !== bases.length) {
|
|
444
|
+
throw new Error("");
|
|
445
|
+
}
|
|
446
|
+
for (var i = 0; i < args.length; i++) {
|
|
447
|
+
if (args[i] !== bases[i]) {
|
|
448
|
+
throw new Error("");
|
|
449
|
+
}
|
|
450
|
+
}
|
|
424
451
|
return this;
|
|
425
452
|
}
|
|
426
453
|
|
|
@@ -510,16 +537,21 @@ Dp.build = function(/* param1, param2, ... */) {
|
|
|
510
537
|
var argc = args.length;
|
|
511
538
|
var built = Object.create(nodePrototype);
|
|
512
539
|
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
540
|
+
if (!self.finalized) {
|
|
541
|
+
throw new Error(
|
|
542
|
+
"attempting to instantiate unfinalized type " +
|
|
543
|
+
self.typeName
|
|
544
|
+
);
|
|
545
|
+
}
|
|
516
546
|
|
|
517
547
|
function add(param, i) {
|
|
518
548
|
if (hasOwn.call(built, param))
|
|
519
549
|
return;
|
|
520
550
|
|
|
521
551
|
var all = self.allFields;
|
|
522
|
-
|
|
552
|
+
if (!hasOwn.call(all, param)) {
|
|
553
|
+
throw new Error("" + param);
|
|
554
|
+
}
|
|
523
555
|
|
|
524
556
|
var field = all[param];
|
|
525
557
|
var type = field.type;
|
|
@@ -537,12 +569,11 @@ Dp.build = function(/* param1, param2, ... */) {
|
|
|
537
569
|
self.buildParams.map(function(name) {
|
|
538
570
|
return all[name];
|
|
539
571
|
}).join(", ") + ")";
|
|
540
|
-
|
|
572
|
+
throw new Error(message);
|
|
541
573
|
}
|
|
542
574
|
|
|
543
575
|
if (!type.check(value)) {
|
|
544
|
-
|
|
545
|
-
false,
|
|
576
|
+
throw new Error(
|
|
546
577
|
shallowStringify(value) +
|
|
547
578
|
" does not match field " + field +
|
|
548
579
|
" of type " + self.typeName
|
|
@@ -563,7 +594,9 @@ Dp.build = function(/* param1, param2, ... */) {
|
|
|
563
594
|
});
|
|
564
595
|
|
|
565
596
|
// Make sure that the "type" field was filled automatically.
|
|
566
|
-
|
|
597
|
+
if (built.type !== self.typeName) {
|
|
598
|
+
throw new Error("");
|
|
599
|
+
}
|
|
567
600
|
|
|
568
601
|
return built;
|
|
569
602
|
}
|
|
@@ -623,8 +656,7 @@ function getFieldNames(object) {
|
|
|
623
656
|
}
|
|
624
657
|
|
|
625
658
|
if ("type" in object) {
|
|
626
|
-
|
|
627
|
-
false,
|
|
659
|
+
throw new Error(
|
|
628
660
|
"did not recognize object of type " +
|
|
629
661
|
JSON.stringify(object.type)
|
|
630
662
|
);
|
|
@@ -693,7 +725,7 @@ Dp.finalize = function() {
|
|
|
693
725
|
JSON.stringify(name) +
|
|
694
726
|
" for subtype " +
|
|
695
727
|
JSON.stringify(self.typeName);
|
|
696
|
-
|
|
728
|
+
throw new Error(message);
|
|
697
729
|
}
|
|
698
730
|
});
|
|
699
731
|
|
|
@@ -754,7 +786,9 @@ function populateSupertypeList(typeName, list) {
|
|
|
754
786
|
for (var pos = 0; pos < list.length; ++pos) {
|
|
755
787
|
typeName = list[pos];
|
|
756
788
|
var d = defCache[typeName];
|
|
757
|
-
|
|
789
|
+
if (d.finalized !== true) {
|
|
790
|
+
throw new Error("");
|
|
791
|
+
}
|
|
758
792
|
|
|
759
793
|
// If we saw typeName earlier in the breadth-first traversal,
|
|
760
794
|
// delete the last-seen occurrence.
|