UNPKG

17.6 kBJavaScriptView Raw
1/**
2 * Copyright 2014 Shape Security, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License")
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17"use strict";
18
19// istanbul ignore next
20
21var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
22
23// istanbul ignore next
24
25var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
26
27// istanbul ignore next
28
29function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
30
31// istanbul ignore next
32
33function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
34
35require("es6-map/implement");
36
37var _objectAssign = require("object-assign");
38
39var objectAssign = _objectAssign;
40
41var _multimap = require("multimap");
42
43// FIXME: remove this when collections/multi-map is working
44var MultiMap = _multimap;
45MultiMap.prototype.addEach = function (otherMap) {
46 // istanbul ignore next
47
48 var _this = this;
49
50 otherMap.forEachEntry(function (v, k) {
51 _this.set.apply(_this, [k].concat(v));
52 });
53 return this;
54};
55
56var identity = undefined; // initialised below EarlyErrorState
57
58var EarlyErrorState = (function () {
59 function EarlyErrorState() {
60 _classCallCheck(this, EarlyErrorState);
61
62 this.errors = [];
63 // errors that are only errors in strict mode code
64 this.strictErrors = [];
65
66 // Label values used in LabeledStatement nodes; cleared at function boundaries
67 this.usedLabelNames = [];
68
69 // BreakStatement nodes; cleared at iteration; switch; and function boundaries
70 this.freeBreakStatements = [];
71 // ContinueStatement nodes; cleared at
72 this.freeContinueStatements = [];
73
74 // labeled BreakStatement nodes; cleared at LabeledStatement with same Label and function boundaries
75 this.freeLabeledBreakStatements = [];
76 // labeled ContinueStatement nodes; cleared at labeled iteration statement with same Label and function boundaries
77 this.freeLabeledContinueStatements = [];
78
79 // NewTargetExpression nodes; cleared at function (besides arrow expression) boundaries
80 this.newTargetExpressions = [];
81
82 // BindingIdentifier nodes; cleared at containing declaration node
83 this.boundNames = new MultiMap();
84 // BindingIdentifiers that were found to be in a lexical binding position
85 this.lexicallyDeclaredNames = new MultiMap();
86 // BindingIdentifiers that were the name of a FunctionDeclaration
87 this.functionDeclarationNames = new MultiMap();
88 // BindingIdentifiers that were found to be in a variable binding position
89 this.varDeclaredNames = new MultiMap();
90 // BindingIdentifiers that were found to be in a variable binding position
91 this.forOfVarDeclaredNames = [];
92
93 // Names that this module exports
94 this.exportedNames = new MultiMap();
95 // Locally declared names that are referenced in export declarations
96 this.exportedBindings = new MultiMap();
97
98 // CallExpressions with Super callee
99 this.superCallExpressions = [];
100 // SuperCall expressions in the context of a Method named "constructor"
101 this.superCallExpressionsInConstructorMethod = [];
102 // MemberExpressions with Super object
103 this.superPropertyExpressions = [];
104
105 // YieldExpression and YieldGeneratorExpression nodes; cleared at function boundaries
106 this.yieldExpressions = [];
107 }
108
109 _createClass(EarlyErrorState, [{
110 key: "addFreeBreakStatement",
111 value: function addFreeBreakStatement(s) {
112 this.freeBreakStatements.push(s);
113 return this;
114 }
115 }, {
116 key: "addFreeLabeledBreakStatement",
117 value: function addFreeLabeledBreakStatement(s) {
118 this.freeLabeledBreakStatements.push(s);
119 return this;
120 }
121 }, {
122 key: "clearFreeBreakStatements",
123 value: function clearFreeBreakStatements() {
124 this.freeBreakStatements = [];
125 return this;
126 }
127 }, {
128 key: "addFreeContinueStatement",
129 value: function addFreeContinueStatement(s) {
130 this.freeContinueStatements.push(s);
131 return this;
132 }
133 }, {
134 key: "addFreeLabeledContinueStatement",
135 value: function addFreeLabeledContinueStatement(s) {
136 this.freeLabeledContinueStatements.push(s);
137 return this;
138 }
139 }, {
140 key: "clearFreeContinueStatements",
141 value: function clearFreeContinueStatements() {
142 this.freeContinueStatements = [];
143 return this;
144 }
145 }, {
146 key: "enforceFreeBreakStatementErrors",
147 value: function enforceFreeBreakStatementErrors(createError) {
148 [].push.apply(this.errors, this.freeBreakStatements.map(createError));
149 this.freeBreakStatements = [];
150 return this;
151 }
152 }, {
153 key: "enforceFreeLabeledBreakStatementErrors",
154 value: function enforceFreeLabeledBreakStatementErrors(createError) {
155 [].push.apply(this.errors, this.freeLabeledBreakStatements.map(createError));
156 this.freeLabeledBreakStatements = [];
157 return this;
158 }
159 }, {
160 key: "enforceFreeContinueStatementErrors",
161 value: function enforceFreeContinueStatementErrors(createError) {
162 [].push.apply(this.errors, this.freeContinueStatements.map(createError));
163 this.freeContinueStatements = [];
164 return this;
165 }
166 }, {
167 key: "enforceFreeLabeledContinueStatementErrors",
168 value: function enforceFreeLabeledContinueStatementErrors(createError) {
169 [].push.apply(this.errors, this.freeLabeledContinueStatements.map(createError));
170 this.freeLabeledContinueStatements = [];
171 return this;
172 }
173 }, {
174 key: "observeIterationLabel",
175 value: function observeIterationLabel(label) {
176 this.usedLabelNames.push(label);
177 this.freeLabeledBreakStatements = this.freeLabeledBreakStatements.filter(function (s) {
178 return s.label !== label;
179 });
180 this.freeLabeledContinueStatements = this.freeLabeledContinueStatements.filter(function (s) {
181 return s.label !== label;
182 });
183 return this;
184 }
185 }, {
186 key: "observeNonIterationLabel",
187 value: function observeNonIterationLabel(label) {
188 this.usedLabelNames.push(label);
189 this.freeLabeledBreakStatements = this.freeLabeledBreakStatements.filter(function (s) {
190 return s.label !== label;
191 });
192 return this;
193 }
194 }, {
195 key: "clearUsedLabelNames",
196 value: function clearUsedLabelNames() {
197 this.usedLabelNames = [];
198 return this;
199 }
200 }, {
201 key: "observeSuperCallExpression",
202 value: function observeSuperCallExpression(node) {
203 this.superCallExpressions.push(node);
204 return this;
205 }
206 }, {
207 key: "observeConstructorMethod",
208 value: function observeConstructorMethod() {
209 this.superCallExpressionsInConstructorMethod = this.superCallExpressions;
210 this.superCallExpressions = [];
211 return this;
212 }
213 }, {
214 key: "clearSuperCallExpressionsInConstructorMethod",
215 value: function clearSuperCallExpressionsInConstructorMethod() {
216 this.superCallExpressionsInConstructorMethod = [];
217 return this;
218 }
219 }, {
220 key: "enforceSuperCallExpressions",
221 value: function enforceSuperCallExpressions(createError) {
222 [].push.apply(this.errors, this.superCallExpressions.map(createError));
223 [].push.apply(this.errors, this.superCallExpressionsInConstructorMethod.map(createError));
224 this.superCallExpressions = [];
225 this.superCallExpressionsInConstructorMethod = [];
226 return this;
227 }
228 }, {
229 key: "enforceSuperCallExpressionsInConstructorMethod",
230 value: function enforceSuperCallExpressionsInConstructorMethod(createError) {
231 [].push.apply(this.errors, this.superCallExpressionsInConstructorMethod.map(createError));
232 this.superCallExpressionsInConstructorMethod = [];
233 return this;
234 }
235 }, {
236 key: "observeSuperPropertyExpression",
237 value: function observeSuperPropertyExpression(node) {
238 this.superPropertyExpressions.push(node);
239 return this;
240 }
241 }, {
242 key: "clearSuperPropertyExpressions",
243 value: function clearSuperPropertyExpressions() {
244 this.superPropertyExpressions = [];
245 return this;
246 }
247 }, {
248 key: "enforceSuperPropertyExpressions",
249 value: function enforceSuperPropertyExpressions(createError) {
250 [].push.apply(this.errors, this.superPropertyExpressions.map(createError));
251 this.superPropertyExpressions = [];
252 return this;
253 }
254 }, {
255 key: "observeNewTargetExpression",
256 value: function observeNewTargetExpression(node) {
257 this.newTargetExpressions.push(node);
258 return this;
259 }
260 }, {
261 key: "clearNewTargetExpressions",
262 value: function clearNewTargetExpressions() {
263 this.newTargetExpressions = [];
264 return this;
265 }
266 }, {
267 key: "bindName",
268 value: function bindName(name, node) {
269 this.boundNames.set(name, node);
270 return this;
271 }
272 }, {
273 key: "clearBoundNames",
274 value: function clearBoundNames() {
275 this.boundNames = new MultiMap();
276 return this;
277 }
278 }, {
279 key: "observeLexicalDeclaration",
280 value: function observeLexicalDeclaration() {
281 this.lexicallyDeclaredNames.addEach(this.boundNames);
282 this.boundNames = new MultiMap();
283 return this;
284 }
285 }, {
286 key: "observeLexicalBoundary",
287 value: function observeLexicalBoundary() {
288 this.previousLexicallyDeclaredNames = this.lexicallyDeclaredNames;
289 this.lexicallyDeclaredNames = new MultiMap();
290 this.functionDeclarationNames = new MultiMap();
291 return this;
292 }
293 }, {
294 key: "enforceDuplicateLexicallyDeclaredNames",
295 value: function enforceDuplicateLexicallyDeclaredNames(createError) {
296 // istanbul ignore next
297
298 var _this2 = this;
299
300 this.lexicallyDeclaredNames.forEachEntry(function (nodes /*, bindingName*/) {
301 if (nodes.length > 1) {
302 nodes.slice(1).forEach(function (dupeNode) {
303 _this2.addError(createError(dupeNode));
304 });
305 }
306 });
307 return this;
308 }
309 }, {
310 key: "enforceConflictingLexicallyDeclaredNames",
311 value: function enforceConflictingLexicallyDeclaredNames(otherNames, createError) {
312 // istanbul ignore next
313
314 var _this3 = this;
315
316 this.lexicallyDeclaredNames.forEachEntry(function (nodes, bindingName) {
317 if (otherNames.has(bindingName)) {
318 nodes.forEach(function (conflictingNode) {
319 _this3.addError(createError(conflictingNode));
320 });
321 }
322 });
323 return this;
324 }
325 }, {
326 key: "observeFunctionDeclaration",
327 value: function observeFunctionDeclaration() {
328 this.observeVarBoundary();
329 this.functionDeclarationNames.addEach(this.boundNames);
330 this.boundNames = new MultiMap();
331 return this;
332 }
333 }, {
334 key: "functionDeclarationNamesAreLexical",
335 value: function functionDeclarationNamesAreLexical() {
336 this.lexicallyDeclaredNames.addEach(this.functionDeclarationNames);
337 this.functionDeclarationNames = new MultiMap();
338 return this;
339 }
340 }, {
341 key: "observeVarDeclaration",
342 value: function observeVarDeclaration() {
343 this.varDeclaredNames.addEach(this.boundNames);
344 this.boundNames = new MultiMap();
345 return this;
346 }
347 }, {
348 key: "recordForOfVars",
349 value: function recordForOfVars() {
350 // istanbul ignore next
351
352 var _this4 = this;
353
354 this.varDeclaredNames.forEach(function (bindingIdentifier) {
355 _this4.forOfVarDeclaredNames.push(bindingIdentifier);
356 });
357 return this;
358 }
359 }, {
360 key: "observeVarBoundary",
361 value: function observeVarBoundary() {
362 this.lexicallyDeclaredNames = new MultiMap();
363 this.functionDeclarationNames = new MultiMap();
364 this.varDeclaredNames = new MultiMap();
365 this.forOfVarDeclaredNames = [];
366 return this;
367 }
368 }, {
369 key: "exportName",
370 value: function exportName(name, node) {
371 this.exportedNames.set(name, node);
372 return this;
373 }
374 }, {
375 key: "exportDeclaredNames",
376 value: function exportDeclaredNames() {
377 this.exportedNames.addEach(this.lexicallyDeclaredNames).addEach(this.varDeclaredNames);
378 this.exportedBindings.addEach(this.lexicallyDeclaredNames).addEach(this.varDeclaredNames);
379 return this;
380 }
381 }, {
382 key: "exportBinding",
383 value: function exportBinding(name, node) {
384 this.exportedBindings.set(name, node);
385 return this;
386 }
387 }, {
388 key: "clearExportedBindings",
389 value: function clearExportedBindings() {
390 this.exportedBindings = new MultiMap();
391 return this;
392 }
393 }, {
394 key: "observeYieldExpression",
395 value: function observeYieldExpression(node) {
396 this.yieldExpressions.push(node);
397 return this;
398 }
399 }, {
400 key: "clearYieldExpressions",
401 value: function clearYieldExpressions() {
402 this.yieldExpressions = [];
403 return this;
404 }
405 }, {
406 key: "addError",
407 value: function addError(e) {
408 this.errors.push(e);
409 return this;
410 }
411 }, {
412 key: "addStrictError",
413 value: function addStrictError(e) {
414 this.strictErrors.push(e);
415 return this;
416 }
417 }, {
418 key: "enforceStrictErrors",
419 value: function enforceStrictErrors() {
420 [].push.apply(this.errors, this.strictErrors);
421 this.strictErrors = [];
422 return this;
423 }
424
425 // MONOID IMPLEMENTATION
426
427 }, {
428 key: "concat",
429 value: function concat(s) {
430 if (this === identity) return s;
431 if (s === identity) return this;
432 [].push.apply(this.errors, s.errors);
433 [].push.apply(this.strictErrors, s.strictErrors);
434 [].push.apply(this.usedLabelNames, s.usedLabelNames);
435 [].push.apply(this.freeBreakStatements, s.freeBreakStatements);
436 [].push.apply(this.freeContinueStatements, s.freeContinueStatements);
437 [].push.apply(this.freeLabeledBreakStatements, s.freeLabeledBreakStatements);
438 [].push.apply(this.freeLabeledContinueStatements, s.freeLabeledContinueStatements);
439 [].push.apply(this.newTargetExpressions, s.newTargetExpressions);
440 this.boundNames.addEach(s.boundNames);
441 this.lexicallyDeclaredNames.addEach(s.lexicallyDeclaredNames);
442 this.functionDeclarationNames.addEach(s.functionDeclarationNames);
443 this.varDeclaredNames.addEach(s.varDeclaredNames);
444 [].push.apply(this.forOfVarDeclaredNames, s.forOfVarDeclaredNames);
445 this.exportedNames.addEach(s.exportedNames);
446 this.exportedBindings.addEach(s.exportedBindings);
447 [].push.apply(this.superCallExpressions, s.superCallExpressions);
448 [].push.apply(this.superCallExpressionsInConstructorMethod, s.superCallExpressionsInConstructorMethod);
449 [].push.apply(this.superPropertyExpressions, s.superPropertyExpressions);
450 [].push.apply(this.yieldExpressions, s.yieldExpressions);
451 return this;
452 }
453 }], [{
454 key: "empty",
455 value: function empty() {
456 return identity;
457 }
458 }]);
459
460 return EarlyErrorState;
461})();
462
463exports.EarlyErrorState = EarlyErrorState;
464
465identity = new EarlyErrorState();
466Object.getOwnPropertyNames(EarlyErrorState.prototype).forEach(function (methodName) {
467 if (methodName === "constructor") return;
468 Object.defineProperty(identity, methodName, {
469 value: function value() {
470 return EarlyErrorState.prototype[methodName].apply(new EarlyErrorState(), arguments);
471 },
472 enumerable: false,
473 writable: true,
474 configurable: true
475 });
476});
477
478var EarlyError = (function (_Error) {
479 _inherits(EarlyError, _Error);
480
481 function EarlyError(node, message) {
482 _classCallCheck(this, EarlyError);
483
484 _get(Object.getPrototypeOf(EarlyError.prototype), "constructor", this).call(this, message);
485 this.node = node;
486 this.message = message;
487 }
488
489 return EarlyError;
490})(Error);
491
492exports.EarlyError = EarlyError;
\No newline at end of file