Spaces:
Running
Running
; | |
Object.defineProperty(exports, '__esModule', { value: true }); | |
var core = require('@babel/core'); | |
var helperPluginUtils = require('@babel/helper-plugin-utils'); | |
var helperEnvironmentVisitor = require('@babel/helper-environment-visitor'); | |
function isNameOrLength(key) { | |
if (core.types.isIdentifier(key)) { | |
return key.name === "name" || key.name === "length"; | |
} | |
if (core.types.isStringLiteral(key)) { | |
return key.value === "name" || key.value === "length"; | |
} | |
return false; | |
} | |
function isStaticFieldWithValue(node) { | |
return (core.types.isClassProperty(node) || core.types.isClassPrivateProperty(node)) && node.static && !!node.value; | |
} | |
const hasReferenceVisitor = { | |
ReferencedIdentifier(path, state) { | |
if (path.node.name === state.name) { | |
state.ref(); | |
path.stop(); | |
} | |
}, | |
Scope(path, { | |
name | |
}) { | |
if (path.scope.hasOwnBinding(name)) { | |
path.skip(); | |
} | |
} | |
}; | |
function isReferenceOrThis(node, name) { | |
return core.types.isThisExpression(node) || name && core.types.isIdentifier(node, { | |
name | |
}); | |
} | |
const hasReferenceOrThisVisitor = { | |
"ThisExpression|ReferencedIdentifier"(path, state) { | |
if (isReferenceOrThis(path.node, state.name)) { | |
state.ref(); | |
path.stop(); | |
} | |
}, | |
FunctionParent(path, state) { | |
if (path.isArrowFunctionExpression()) return; | |
if (state.name && !path.scope.hasOwnBinding(state.name)) { | |
path.traverse(hasReferenceVisitor, state); | |
} | |
path.skip(); | |
if (path.isMethod()) { | |
helperEnvironmentVisitor.requeueComputedKeyAndDecorators(path); | |
} | |
} | |
}; | |
function getPotentiallyBuggyFieldsIndexes(path) { | |
var _path$node$id; | |
const buggyPublicStaticFieldsIndexes = []; | |
let classReferenced = false; | |
const className = (_path$node$id = path.node.id) == null ? void 0 : _path$node$id.name; | |
const hasReferenceState = { | |
name: className, | |
ref: () => classReferenced = true | |
}; | |
if (className) { | |
for (const el of path.get("body.body")) { | |
if (el.node.computed) { | |
el.get("key").traverse(hasReferenceVisitor, hasReferenceState); | |
if (classReferenced) break; | |
} | |
} | |
} | |
let nextPotentiallyBuggy = false; | |
const { | |
body | |
} = path.node.body; | |
for (let i = 0; i < body.length; i++) { | |
const node = body[i]; | |
if (!nextPotentiallyBuggy) { | |
if (core.types.isStaticBlock(node)) { | |
classReferenced = true; | |
nextPotentiallyBuggy = true; | |
} else if (isStaticFieldWithValue(node)) { | |
if (!classReferenced) { | |
if (isReferenceOrThis(node.value, className)) { | |
classReferenced = true; | |
} else { | |
path.get(`body.body.${i}.value`).traverse(hasReferenceOrThisVisitor, hasReferenceState); | |
} | |
} | |
if (classReferenced) { | |
nextPotentiallyBuggy = !path.scope.isPure(node.value); | |
} | |
} | |
} | |
if (core.types.isClassProperty(node, { | |
static: true | |
}) && (nextPotentiallyBuggy || node.computed || isNameOrLength(node.key))) { | |
buggyPublicStaticFieldsIndexes.push(i); | |
} | |
} | |
return buggyPublicStaticFieldsIndexes; | |
} | |
function getNameOrLengthStaticFieldsIndexes(path) { | |
const indexes = []; | |
const { | |
body | |
} = path.node.body; | |
for (let i = 0; i < body.length; i++) { | |
const node = body[i]; | |
if (core.types.isClassProperty(node, { | |
static: true, | |
computed: false | |
}) && isNameOrLength(node.key)) { | |
indexes.push(i); | |
} | |
} | |
return indexes; | |
} | |
function toRanges(nums) { | |
const ranges = []; | |
if (nums.length === 0) return ranges; | |
let start = nums[0]; | |
let end = start + 1; | |
for (let i = 1; i < nums.length; i++) { | |
if (nums[i] <= nums[i - 1]) { | |
throw new Error("Internal Babel error: nums must be in ascending order"); | |
} | |
if (nums[i] === end) { | |
end++; | |
} else { | |
ranges.push([start, end]); | |
start = nums[i]; | |
end = start + 1; | |
} | |
} | |
ranges.push([start, end]); | |
return ranges; | |
} | |
function buildFieldsReplacement(fields, scope, file) { | |
return core.types.staticBlock(fields.map(field => { | |
const key = field.computed || !core.types.isIdentifier(field.key) ? field.key : core.types.stringLiteral(field.key.name); | |
return core.types.expressionStatement(core.types.callExpression(file.addHelper("defineProperty"), [core.types.thisExpression(), key, field.value || scope.buildUndefinedNode()])); | |
})); | |
} | |
var index = helperPluginUtils.declare(api => { | |
api.assertVersion(7); | |
const setPublicClassFields = api.assumption("setPublicClassFields"); | |
return { | |
name: "bugfix-v8-static-class-fields-redefine-readonly", | |
visitor: { | |
Class(path) { | |
const ranges = toRanges(setPublicClassFields ? getNameOrLengthStaticFieldsIndexes(path) : getPotentiallyBuggyFieldsIndexes(path)); | |
for (let i = ranges.length - 1; i >= 0; i--) { | |
const [start, end] = ranges[i]; | |
const startPath = path.get("body.body")[start]; | |
startPath.replaceWith(buildFieldsReplacement(path.node.body.body.slice(start, end), path.scope, this.file)); | |
for (let j = end - 1; j > start; j--) { | |
path.get("body.body")[j].remove(); | |
} | |
} | |
} | |
} | |
}; | |
}); | |
exports.default = index; | |
//# sourceMappingURL=index.js.map | |