[79a0317] | 1 | 'use strict';
|
---|
| 2 |
|
---|
| 3 | Object.defineProperty(exports, '__esModule', { value: true });
|
---|
| 4 |
|
---|
| 5 | var core = require('@babel/core');
|
---|
| 6 | var helperPluginUtils = require('@babel/helper-plugin-utils');
|
---|
| 7 |
|
---|
| 8 | function isNameOrLength(key) {
|
---|
| 9 | if (core.types.isIdentifier(key)) {
|
---|
| 10 | return key.name === "name" || key.name === "length";
|
---|
| 11 | }
|
---|
| 12 | if (core.types.isStringLiteral(key)) {
|
---|
| 13 | return key.value === "name" || key.value === "length";
|
---|
| 14 | }
|
---|
| 15 | return false;
|
---|
| 16 | }
|
---|
| 17 | function isStaticFieldWithValue(node) {
|
---|
| 18 | return (core.types.isClassProperty(node) || core.types.isClassPrivateProperty(node)) && node.static && !!node.value;
|
---|
| 19 | }
|
---|
| 20 | const hasReferenceVisitor = {
|
---|
| 21 | ReferencedIdentifier(path, state) {
|
---|
| 22 | if (path.node.name === state.name) {
|
---|
| 23 | state.ref();
|
---|
| 24 | path.stop();
|
---|
| 25 | }
|
---|
| 26 | },
|
---|
| 27 | Scope(path, {
|
---|
| 28 | name
|
---|
| 29 | }) {
|
---|
| 30 | if (path.scope.hasOwnBinding(name)) {
|
---|
| 31 | path.skip();
|
---|
| 32 | }
|
---|
| 33 | }
|
---|
| 34 | };
|
---|
| 35 | function isReferenceOrThis(node, name) {
|
---|
| 36 | return core.types.isThisExpression(node) || name && core.types.isIdentifier(node, {
|
---|
| 37 | name
|
---|
| 38 | });
|
---|
| 39 | }
|
---|
| 40 | const hasReferenceOrThisVisitor = {
|
---|
| 41 | "ThisExpression|ReferencedIdentifier"(path, state) {
|
---|
| 42 | if (isReferenceOrThis(path.node, state.name)) {
|
---|
| 43 | state.ref();
|
---|
| 44 | path.stop();
|
---|
| 45 | }
|
---|
| 46 | },
|
---|
| 47 | FunctionParent(path, state) {
|
---|
| 48 | if (path.isArrowFunctionExpression()) return;
|
---|
| 49 | if (state.name && !path.scope.hasOwnBinding(state.name)) {
|
---|
| 50 | path.traverse(hasReferenceVisitor, state);
|
---|
| 51 | }
|
---|
| 52 | path.skip();
|
---|
| 53 | if (path.isMethod()) {
|
---|
| 54 | if (path.requeueComputedKeyAndDecorators) {
|
---|
| 55 | path.requeueComputedKeyAndDecorators();
|
---|
| 56 | } else {
|
---|
| 57 | require("@babel/traverse").NodePath.prototype.requeueComputedKeyAndDecorators.call(path);
|
---|
| 58 | }
|
---|
| 59 | }
|
---|
| 60 | }
|
---|
| 61 | };
|
---|
| 62 | function getPotentiallyBuggyFieldsIndexes(path) {
|
---|
| 63 | var _path$node$id;
|
---|
| 64 | const buggyPublicStaticFieldsIndexes = [];
|
---|
| 65 | let classReferenced = false;
|
---|
| 66 | const className = (_path$node$id = path.node.id) == null ? void 0 : _path$node$id.name;
|
---|
| 67 | const hasReferenceState = {
|
---|
| 68 | name: className,
|
---|
| 69 | ref: () => classReferenced = true
|
---|
| 70 | };
|
---|
| 71 | if (className) {
|
---|
| 72 | for (const el of path.get("body.body")) {
|
---|
| 73 | if (el.node.computed) {
|
---|
| 74 | el.get("key").traverse(hasReferenceVisitor, hasReferenceState);
|
---|
| 75 | if (classReferenced) break;
|
---|
| 76 | }
|
---|
| 77 | }
|
---|
| 78 | }
|
---|
| 79 | let nextPotentiallyBuggy = false;
|
---|
| 80 | const {
|
---|
| 81 | body
|
---|
| 82 | } = path.node.body;
|
---|
| 83 | for (let i = 0; i < body.length; i++) {
|
---|
| 84 | const node = body[i];
|
---|
| 85 | if (!nextPotentiallyBuggy) {
|
---|
| 86 | if (core.types.isStaticBlock(node)) {
|
---|
| 87 | classReferenced = true;
|
---|
| 88 | nextPotentiallyBuggy = true;
|
---|
| 89 | } else if (isStaticFieldWithValue(node)) {
|
---|
| 90 | if (!classReferenced) {
|
---|
| 91 | if (isReferenceOrThis(node.value, className)) {
|
---|
| 92 | classReferenced = true;
|
---|
| 93 | } else {
|
---|
| 94 | path.get(`body.body.${i}.value`).traverse(hasReferenceOrThisVisitor, hasReferenceState);
|
---|
| 95 | }
|
---|
| 96 | }
|
---|
| 97 | if (classReferenced) {
|
---|
| 98 | nextPotentiallyBuggy = !path.scope.isPure(node.value);
|
---|
| 99 | }
|
---|
| 100 | }
|
---|
| 101 | }
|
---|
| 102 | if (core.types.isClassProperty(node, {
|
---|
| 103 | static: true
|
---|
| 104 | }) && (nextPotentiallyBuggy || node.computed || isNameOrLength(node.key))) {
|
---|
| 105 | buggyPublicStaticFieldsIndexes.push(i);
|
---|
| 106 | }
|
---|
| 107 | }
|
---|
| 108 | return buggyPublicStaticFieldsIndexes;
|
---|
| 109 | }
|
---|
| 110 | function getNameOrLengthStaticFieldsIndexes(path) {
|
---|
| 111 | const indexes = [];
|
---|
| 112 | const {
|
---|
| 113 | body
|
---|
| 114 | } = path.node.body;
|
---|
| 115 | for (let i = 0; i < body.length; i++) {
|
---|
| 116 | const node = body[i];
|
---|
| 117 | if (core.types.isClassProperty(node, {
|
---|
| 118 | static: true,
|
---|
| 119 | computed: false
|
---|
| 120 | }) && isNameOrLength(node.key)) {
|
---|
| 121 | indexes.push(i);
|
---|
| 122 | }
|
---|
| 123 | }
|
---|
| 124 | return indexes;
|
---|
| 125 | }
|
---|
| 126 | function toRanges(nums) {
|
---|
| 127 | const ranges = [];
|
---|
| 128 | if (nums.length === 0) return ranges;
|
---|
| 129 | let start = nums[0];
|
---|
| 130 | let end = start + 1;
|
---|
| 131 | for (let i = 1; i < nums.length; i++) {
|
---|
| 132 | if (nums[i] <= nums[i - 1]) {
|
---|
| 133 | throw new Error("Internal Babel error: nums must be in ascending order");
|
---|
| 134 | }
|
---|
| 135 | if (nums[i] === end) {
|
---|
| 136 | end++;
|
---|
| 137 | } else {
|
---|
| 138 | ranges.push([start, end]);
|
---|
| 139 | start = nums[i];
|
---|
| 140 | end = start + 1;
|
---|
| 141 | }
|
---|
| 142 | }
|
---|
| 143 | ranges.push([start, end]);
|
---|
| 144 | return ranges;
|
---|
| 145 | }
|
---|
| 146 |
|
---|
| 147 | function buildFieldsReplacement(fields, scope, file) {
|
---|
| 148 | return core.types.staticBlock(fields.map(field => {
|
---|
| 149 | const key = field.computed || !core.types.isIdentifier(field.key) ? field.key : core.types.stringLiteral(field.key.name);
|
---|
| 150 | return core.types.expressionStatement(core.types.callExpression(file.addHelper("defineProperty"), [core.types.thisExpression(), key, field.value || scope.buildUndefinedNode()]));
|
---|
| 151 | }));
|
---|
| 152 | }
|
---|
| 153 | var index = helperPluginUtils.declare(api => {
|
---|
| 154 | api.assertVersion("^7.0.0-0 || >8.0.0-alpha <8.0.0-beta");
|
---|
| 155 | const setPublicClassFields = api.assumption("setPublicClassFields");
|
---|
| 156 | return {
|
---|
| 157 | name: "bugfix-v8-static-class-fields-redefine-readonly",
|
---|
| 158 | visitor: {
|
---|
| 159 | Class(path) {
|
---|
| 160 | const ranges = toRanges(setPublicClassFields ? getNameOrLengthStaticFieldsIndexes(path) : getPotentiallyBuggyFieldsIndexes(path));
|
---|
| 161 | for (let i = ranges.length - 1; i >= 0; i--) {
|
---|
| 162 | const [start, end] = ranges[i];
|
---|
| 163 | const startPath = path.get("body.body")[start];
|
---|
| 164 | startPath.replaceWith(buildFieldsReplacement(path.node.body.body.slice(start, end), path.scope, this.file));
|
---|
| 165 | for (let j = end - 1; j > start; j--) {
|
---|
| 166 | path.get("body.body")[j].remove();
|
---|
| 167 | }
|
---|
| 168 | }
|
---|
| 169 | }
|
---|
| 170 | }
|
---|
| 171 | };
|
---|
| 172 | });
|
---|
| 173 |
|
---|
| 174 | exports.default = index;
|
---|
| 175 | //# sourceMappingURL=index.js.map
|
---|