You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					137 lines
				
				4.9 KiB
			
		
		
			
		
	
	
					137 lines
				
				4.9 KiB
			| 
											3 years ago
										 | "use strict"; | ||
|  | 
 | ||
|  | Object.defineProperty(exports, "__esModule", { | ||
|  |   value: true | ||
|  | }); | ||
|  | exports.validateUsage = validateUsage; | ||
|  | var _core = require("@babel/core"); | ||
|  | function validateUsage(path, state, tdzEnabled) { | ||
|  |   const dynamicTDZNames = []; | ||
|  |   for (const name of Object.keys(path.getBindingIdentifiers())) { | ||
|  |     const binding = path.scope.getBinding(name); | ||
|  |     if (!binding) continue; | ||
|  |     if (tdzEnabled) { | ||
|  |       if (injectTDZChecks(binding, state)) dynamicTDZNames.push(name); | ||
|  |     } | ||
|  |     if (path.node.kind === "const") { | ||
|  |       disallowConstantViolations(name, binding, state); | ||
|  |     } | ||
|  |   } | ||
|  |   return dynamicTDZNames; | ||
|  | } | ||
|  | function disallowConstantViolations(name, binding, state) { | ||
|  |   for (const violation of binding.constantViolations) { | ||
|  |     const readOnlyError = state.addHelper("readOnlyError"); | ||
|  |     const throwNode = _core.types.callExpression(readOnlyError, [_core.types.stringLiteral(name)]); | ||
|  |     if (violation.isAssignmentExpression()) { | ||
|  |       const { | ||
|  |         operator, | ||
|  |         left, | ||
|  |         right | ||
|  |       } = violation.node; | ||
|  |       if (operator === "=") { | ||
|  |         const exprs = [right]; | ||
|  |         exprs.push(throwNode); | ||
|  |         violation.replaceWith(_core.types.sequenceExpression(exprs)); | ||
|  |       } else if (["&&=", "||=", "??="].includes(operator)) { | ||
|  |         violation.replaceWith(_core.types.logicalExpression( | ||
|  |         operator.slice(0, -1), left, _core.types.sequenceExpression([right, throwNode]))); | ||
|  |       } else { | ||
|  |         violation.replaceWith(_core.types.sequenceExpression([_core.types.binaryExpression( | ||
|  |         operator.slice(0, -1), left, right), throwNode])); | ||
|  |       } | ||
|  |     } else if (violation.isUpdateExpression()) { | ||
|  |       violation.replaceWith(_core.types.sequenceExpression([_core.types.unaryExpression("+", violation.get("argument").node), throwNode])); | ||
|  |     } else if (violation.isForXStatement()) { | ||
|  |       violation.ensureBlock(); | ||
|  |       violation.get("left").replaceWith(_core.types.variableDeclaration("var", [_core.types.variableDeclarator(violation.scope.generateUidIdentifier(name))])); | ||
|  |       violation.node.body.body.unshift(_core.types.expressionStatement(throwNode)); | ||
|  |     } | ||
|  |   } | ||
|  | } | ||
|  | function getTDZStatus(refPath, bindingPath) { | ||
|  |   const executionStatus = bindingPath._guessExecutionStatusRelativeTo(refPath); | ||
|  |   if (executionStatus === "before") { | ||
|  |     return "outside"; | ||
|  |   } else if (executionStatus === "after") { | ||
|  |     return "inside"; | ||
|  |   } else { | ||
|  |     return "maybe"; | ||
|  |   } | ||
|  | } | ||
|  | const skipTDZChecks = new WeakSet(); | ||
|  | function buildTDZAssert(status, node, state) { | ||
|  |   if (status === "maybe") { | ||
|  |     const clone = _core.types.cloneNode(node); | ||
|  |     skipTDZChecks.add(clone); | ||
|  |     return _core.types.callExpression(state.addHelper("temporalRef"), [ | ||
|  |     clone, _core.types.stringLiteral(node.name)]); | ||
|  |   } else { | ||
|  |     return _core.types.callExpression(state.addHelper("tdz"), [_core.types.stringLiteral(node.name)]); | ||
|  |   } | ||
|  | } | ||
|  | function getTDZReplacement(path, state, id = path.node) { | ||
|  |   var _path$scope$getBindin; | ||
|  |   if (skipTDZChecks.has(id)) return; | ||
|  |   skipTDZChecks.add(id); | ||
|  |   const bindingPath = (_path$scope$getBindin = path.scope.getBinding(id.name)) == null ? void 0 : _path$scope$getBindin.path; | ||
|  |   if (!bindingPath || bindingPath.isFunctionDeclaration()) return; | ||
|  |   const status = getTDZStatus(path, bindingPath); | ||
|  |   if (status === "outside") return; | ||
|  |   if (status === "maybe") { | ||
|  |     bindingPath.parent._tdzThis = true; | ||
|  |   } | ||
|  |   return { | ||
|  |     status, | ||
|  |     node: buildTDZAssert(status, id, state) | ||
|  |   }; | ||
|  | } | ||
|  | function injectTDZChecks(binding, state) { | ||
|  |   const allUsages = new Set(binding.referencePaths); | ||
|  |   binding.constantViolations.forEach(allUsages.add, allUsages); | ||
|  |   let dynamicTdz = false; | ||
|  |   for (const path of binding.constantViolations) { | ||
|  |     const { | ||
|  |       node | ||
|  |     } = path; | ||
|  |     if (skipTDZChecks.has(node)) continue; | ||
|  |     skipTDZChecks.add(node); | ||
|  |     if (path.isUpdateExpression()) { | ||
|  |       const arg = path.get("argument"); | ||
|  |       const replacement = getTDZReplacement(path, state, arg.node); | ||
|  |       if (!replacement) continue; | ||
|  |       if (replacement.status === "maybe") { | ||
|  |         dynamicTdz = true; | ||
|  |         path.insertBefore(replacement.node); | ||
|  |       } else { | ||
|  |         path.replaceWith(replacement.node); | ||
|  |       } | ||
|  |     } else if (path.isAssignmentExpression()) { | ||
|  |       const nodes = []; | ||
|  |       const ids = path.getBindingIdentifiers(); | ||
|  |       for (const name of Object.keys(ids)) { | ||
|  |         const replacement = getTDZReplacement(path, state, ids[name]); | ||
|  |         if (replacement) { | ||
|  |           nodes.push(_core.types.expressionStatement(replacement.node)); | ||
|  |           if (replacement.status === "inside") break; | ||
|  |           if (replacement.status === "maybe") dynamicTdz = true; | ||
|  |         } | ||
|  |       } | ||
|  |       if (nodes.length > 0) path.insertBefore(nodes); | ||
|  |     } | ||
|  |   } | ||
|  |   for (const path of binding.referencePaths) { | ||
|  |     if (path.parentPath.isUpdateExpression()) continue; | ||
|  |     if (path.parentPath.isFor({ | ||
|  |       left: path.node | ||
|  |     })) continue; | ||
|  |     const replacement = getTDZReplacement(path, state); | ||
|  |     if (!replacement) continue; | ||
|  |     if (replacement.status === "maybe") dynamicTdz = true; | ||
|  |     path.replaceWith(replacement.node); | ||
|  |   } | ||
|  |   return dynamicTdz; | ||
|  | } | ||
|  | 
 | ||
|  | //# sourceMappingURL=validation.js.map
 |