@solvprotocol/upgrade-safe-transpiler
Version:
Solidity preprocessor used to generate OpenZeppelin Contracts Upgrade Safe.
112 lines • 4.53 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Transform = void 0;
const lodash_1 = require("lodash");
const src_decoder_1 = require("./solc/src-decoder");
const layout_getter_1 = require("./solc/layout-getter");
const shifts_1 = require("./shifts");
const apply_1 = require("./transformations/apply");
const compare_1 = require("./transformations/compare");
const ast_resolver_1 = require("./ast-resolver");
class Transform {
constructor(input, output, options) {
var _a;
this.state = {};
this.data = new WeakMap();
this.decodeSrc = (0, src_decoder_1.srcDecoder)(output);
this.getLayout = (0, layout_getter_1.layoutGetter)(output);
this.resolver = new ast_resolver_1.ASTResolver(output, options === null || options === void 0 ? void 0 : options.exclude);
for (const source in input.sources) {
if ((_a = options === null || options === void 0 ? void 0 : options.exclude) === null || _a === void 0 ? void 0 : _a.call(options, source)) {
continue;
}
const s = input.sources[source];
if (!('content' in s)) {
throw new Error(`Missing content for ${source}`);
}
const contentBuf = Buffer.from(s.content);
this.state[source] = {
ast: output.sources[source].ast,
original: s.content,
originalBuf: contentBuf,
content: contentBuf,
transformations: [],
shifts: [],
};
}
}
apply(transform) {
for (const source in this.state) {
const { original: originalSource, originalBuf: originalSourceBuf, ast } = this.state[source];
const { resolver, getLayout } = this;
const readOriginal = this.readOriginal.bind(this);
const getData = this.getData.bind(this);
const tools = {
originalSource,
originalSourceBuf,
resolver,
readOriginal,
getData,
getLayout,
};
for (const t of transform(ast, tools)) {
const { content, shifts, transformations } = this.state[source];
insertSortedAndValidate(transformations, t);
const { result, shift } = (0, apply_1.applyTransformation)(t, content, shifts, this);
shifts.push(shift);
this.state[source].content = result;
}
}
}
getData(node) {
let data = this.data.get(node);
if (data === undefined) {
data = {};
this.data.set(node, data);
}
return data;
}
readOriginal(node, type = 'string') {
const { source, start, length } = this.decodeSrc(node.src);
const { originalBuf } = this.state[source];
const buf = originalBuf.slice(start, start + length);
if (type === 'buffer') {
return buf;
}
else {
return buf.toString('utf8');
}
}
read(node) {
const { source, ...bounds } = this.decodeSrc(node.src);
const { shifts, transformations, content } = this.state[source];
const incompatible = (t) => {
const c = (0, compare_1.compareContainment)(t, bounds);
return c === 'partial overlap' || (typeof c === 'number' && c > 0);
};
if (transformations.some(incompatible)) {
throw new Error(`Can't read from segment that has been partially transformed`);
}
const sb = (0, shifts_1.shiftBounds)(shifts, bounds);
return content.slice(sb.start, sb.start + sb.length).toString();
}
results() {
return (0, lodash_1.mapValues)(this.state, s => s.content.toString());
}
asts() {
return Object.values(this.state).map(s => s.ast);
}
}
exports.Transform = Transform;
function insertSortedAndValidate(transformations, t) {
transformations.push(t);
transformations.sort(compare_1.compareTransformations); // checks for overlaps
for (let i = transformations.indexOf(t) + 1; i < transformations.length; i += 1) {
const s = transformations[i];
const c = (0, compare_1.compareContainment)(t, s);
if (typeof c === 'number' && c < 0) {
throw new Error(`A bigger area has already been transformed (${s.kind} > ${t.kind})`);
}
}
}
//# sourceMappingURL=transform.js.map