[79a0317] | 1 | "use strict";
|
---|
| 2 |
|
---|
| 3 | Object.defineProperty(exports, "__esModule", {
|
---|
| 4 | value: true
|
---|
| 5 | });
|
---|
| 6 | exports.validateUsage = validateUsage;
|
---|
| 7 | var _core = require("@babel/core");
|
---|
| 8 | function validateUsage(path, state, tdzEnabled) {
|
---|
| 9 | const dynamicTDZNames = [];
|
---|
| 10 | for (const name of Object.keys(path.getBindingIdentifiers())) {
|
---|
| 11 | const binding = path.scope.getBinding(name);
|
---|
| 12 | if (!binding) continue;
|
---|
| 13 | if (tdzEnabled) {
|
---|
| 14 | if (injectTDZChecks(binding, state)) dynamicTDZNames.push(name);
|
---|
| 15 | }
|
---|
| 16 | if (path.node.kind === "const") {
|
---|
| 17 | disallowConstantViolations(name, binding, state);
|
---|
| 18 | }
|
---|
| 19 | }
|
---|
| 20 | return dynamicTDZNames;
|
---|
| 21 | }
|
---|
| 22 | function disallowConstantViolations(name, binding, state) {
|
---|
| 23 | for (const violation of binding.constantViolations) {
|
---|
| 24 | const readOnlyError = state.addHelper("readOnlyError");
|
---|
| 25 | const throwNode = _core.types.callExpression(readOnlyError, [_core.types.stringLiteral(name)]);
|
---|
| 26 | if (violation.isAssignmentExpression()) {
|
---|
| 27 | const {
|
---|
| 28 | operator,
|
---|
| 29 | left,
|
---|
| 30 | right
|
---|
| 31 | } = violation.node;
|
---|
| 32 | if (operator === "=") {
|
---|
| 33 | const exprs = [right];
|
---|
| 34 | exprs.push(throwNode);
|
---|
| 35 | violation.replaceWith(_core.types.sequenceExpression(exprs));
|
---|
| 36 | } else if (["&&=", "||=", "??="].includes(operator)) {
|
---|
| 37 | violation.replaceWith(_core.types.logicalExpression(operator.slice(0, -1), left, _core.types.sequenceExpression([right, throwNode])));
|
---|
| 38 | } else {
|
---|
| 39 | violation.replaceWith(_core.types.sequenceExpression([_core.types.binaryExpression(operator.slice(0, -1), left, right), throwNode]));
|
---|
| 40 | }
|
---|
| 41 | } else if (violation.isUpdateExpression()) {
|
---|
| 42 | violation.replaceWith(_core.types.sequenceExpression([_core.types.unaryExpression("+", violation.get("argument").node), throwNode]));
|
---|
| 43 | } else if (violation.isForXStatement()) {
|
---|
| 44 | violation.ensureBlock();
|
---|
| 45 | violation.get("left").replaceWith(_core.types.variableDeclaration("var", [_core.types.variableDeclarator(violation.scope.generateUidIdentifier(name))]));
|
---|
| 46 | violation.node.body.body.unshift(_core.types.expressionStatement(throwNode));
|
---|
| 47 | }
|
---|
| 48 | }
|
---|
| 49 | }
|
---|
| 50 | function getTDZStatus(refPath, bindingPath) {
|
---|
| 51 | const executionStatus = bindingPath._guessExecutionStatusRelativeTo(refPath);
|
---|
| 52 | if (executionStatus === "before") {
|
---|
| 53 | return "outside";
|
---|
| 54 | } else if (executionStatus === "after") {
|
---|
| 55 | return "inside";
|
---|
| 56 | } else {
|
---|
| 57 | return "maybe";
|
---|
| 58 | }
|
---|
| 59 | }
|
---|
| 60 | const skipTDZChecks = new WeakSet();
|
---|
| 61 | function buildTDZAssert(status, node, state) {
|
---|
| 62 | if (status === "maybe") {
|
---|
| 63 | const clone = _core.types.cloneNode(node);
|
---|
| 64 | skipTDZChecks.add(clone);
|
---|
| 65 | return _core.types.callExpression(state.addHelper("temporalRef"), [clone, _core.types.stringLiteral(node.name)]);
|
---|
| 66 | } else {
|
---|
| 67 | return _core.types.callExpression(state.addHelper("tdz"), [_core.types.stringLiteral(node.name)]);
|
---|
| 68 | }
|
---|
| 69 | }
|
---|
| 70 | function getTDZReplacement(path, state, id = path.node) {
|
---|
| 71 | var _path$scope$getBindin;
|
---|
| 72 | if (skipTDZChecks.has(id)) return;
|
---|
| 73 | skipTDZChecks.add(id);
|
---|
| 74 | const bindingPath = (_path$scope$getBindin = path.scope.getBinding(id.name)) == null ? void 0 : _path$scope$getBindin.path;
|
---|
| 75 | if (!bindingPath || bindingPath.isFunctionDeclaration()) return;
|
---|
| 76 | const status = getTDZStatus(path, bindingPath);
|
---|
| 77 | if (status === "outside") return;
|
---|
| 78 | if (status === "maybe") {
|
---|
| 79 | bindingPath.parent._tdzThis = true;
|
---|
| 80 | }
|
---|
| 81 | return {
|
---|
| 82 | status,
|
---|
| 83 | node: buildTDZAssert(status, id, state)
|
---|
| 84 | };
|
---|
| 85 | }
|
---|
| 86 | function injectTDZChecks(binding, state) {
|
---|
| 87 | const allUsages = new Set(binding.referencePaths);
|
---|
| 88 | binding.constantViolations.forEach(allUsages.add, allUsages);
|
---|
| 89 | let dynamicTdz = false;
|
---|
| 90 | for (const path of binding.constantViolations) {
|
---|
| 91 | const {
|
---|
| 92 | node
|
---|
| 93 | } = path;
|
---|
| 94 | if (skipTDZChecks.has(node)) continue;
|
---|
| 95 | skipTDZChecks.add(node);
|
---|
| 96 | if (path.isUpdateExpression()) {
|
---|
| 97 | const arg = path.get("argument");
|
---|
| 98 | const replacement = getTDZReplacement(path, state, arg.node);
|
---|
| 99 | if (!replacement) continue;
|
---|
| 100 | if (replacement.status === "maybe") {
|
---|
| 101 | dynamicTdz = true;
|
---|
| 102 | path.insertBefore(replacement.node);
|
---|
| 103 | } else {
|
---|
| 104 | path.replaceWith(replacement.node);
|
---|
| 105 | }
|
---|
| 106 | } else if (path.isAssignmentExpression()) {
|
---|
| 107 | const nodes = [];
|
---|
| 108 | const ids = path.getBindingIdentifiers();
|
---|
| 109 | for (const name of Object.keys(ids)) {
|
---|
| 110 | const replacement = getTDZReplacement(path, state, ids[name]);
|
---|
| 111 | if (replacement) {
|
---|
| 112 | nodes.push(_core.types.expressionStatement(replacement.node));
|
---|
| 113 | if (replacement.status === "inside") break;
|
---|
| 114 | if (replacement.status === "maybe") dynamicTdz = true;
|
---|
| 115 | }
|
---|
| 116 | }
|
---|
| 117 | if (nodes.length > 0) path.insertBefore(nodes);
|
---|
| 118 | }
|
---|
| 119 | }
|
---|
| 120 | for (const path of binding.referencePaths) {
|
---|
| 121 | if (path.parentPath.isUpdateExpression()) continue;
|
---|
| 122 | if (path.parentPath.isFor({
|
---|
| 123 | left: path.node
|
---|
| 124 | })) continue;
|
---|
| 125 | const replacement = getTDZReplacement(path, state);
|
---|
| 126 | if (!replacement) continue;
|
---|
| 127 | if (replacement.status === "maybe") dynamicTdz = true;
|
---|
| 128 | path.replaceWith(replacement.node);
|
---|
| 129 | }
|
---|
| 130 | return dynamicTdz;
|
---|
| 131 | }
|
---|
| 132 |
|
---|
| 133 | //# sourceMappingURL=validation.js.map
|
---|