ember-legacy-class-transform
Version:
The default blueprint for ember-cli addons.
354 lines (347 loc) • 39.1 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.Environment = exports.Program = exports.Heap = exports.Opcode = exports.Scope = undefined;
var _functions = require('./syntax/functions');
var _constants = require('./environment/constants');
var _references = require('./references');
var _attributeManagers = require('./dom/attribute-managers');
var _util = require('@glimmer/util');
class Scope {
constructor(
// the 0th slot is `self`
slots, callerScope,
// named arguments and blocks passed to a layout that uses eval
evalScope,
// locals in scope when the partial was invoked
partialMap) {
this.slots = slots;
this.callerScope = callerScope;
this.evalScope = evalScope;
this.partialMap = partialMap;
}
static root(self, size = 0) {
let refs = new Array(size + 1);
for (let i = 0; i <= size; i++) {
refs[i] = _references.UNDEFINED_REFERENCE;
}
return new Scope(refs, null, null, null).init({ self });
}
static sized(size = 0) {
let refs = new Array(size + 1);
for (let i = 0; i <= size; i++) {
refs[i] = _references.UNDEFINED_REFERENCE;
}
return new Scope(refs, null, null, null);
}
init({ self }) {
this.slots[0] = self;
return this;
}
getSelf() {
return this.get(0);
}
getSymbol(symbol) {
return this.get(symbol);
}
getBlock(symbol) {
return this.get(symbol);
}
getEvalScope() {
return this.evalScope;
}
getPartialMap() {
return this.partialMap;
}
bind(symbol, value) {
this.set(symbol, value);
}
bindSelf(self) {
this.set(0, self);
}
bindSymbol(symbol, value) {
this.set(symbol, value);
}
bindBlock(symbol, value) {
this.set(symbol, value);
}
bindEvalScope(map) {
this.evalScope = map;
}
bindPartialMap(map) {
this.partialMap = map;
}
bindCallerScope(scope) {
this.callerScope = scope;
}
getCallerScope() {
return this.callerScope;
}
child() {
return new Scope(this.slots.slice(), this.callerScope, this.evalScope, this.partialMap);
}
get(index) {
if (index >= this.slots.length) {
throw new RangeError(`BUG: cannot get $${index} from scope; length=${this.slots.length}`);
}
return this.slots[index];
}
set(index, value) {
if (index >= this.slots.length) {
throw new RangeError(`BUG: cannot get $${index} from scope; length=${this.slots.length}`);
}
this.slots[index] = value;
}
}
exports.Scope = Scope;
class Transaction {
constructor() {
this.scheduledInstallManagers = [];
this.scheduledInstallModifiers = [];
this.scheduledUpdateModifierManagers = [];
this.scheduledUpdateModifiers = [];
this.createdComponents = [];
this.createdManagers = [];
this.updatedComponents = [];
this.updatedManagers = [];
this.destructors = [];
}
didCreate(component, manager) {
this.createdComponents.push(component);
this.createdManagers.push(manager);
}
didUpdate(component, manager) {
this.updatedComponents.push(component);
this.updatedManagers.push(manager);
}
scheduleInstallModifier(modifier, manager) {
this.scheduledInstallManagers.push(manager);
this.scheduledInstallModifiers.push(modifier);
}
scheduleUpdateModifier(modifier, manager) {
this.scheduledUpdateModifierManagers.push(manager);
this.scheduledUpdateModifiers.push(modifier);
}
didDestroy(d) {
this.destructors.push(d);
}
commit() {
let { createdComponents, createdManagers } = this;
for (let i = 0; i < createdComponents.length; i++) {
let component = createdComponents[i];
let manager = createdManagers[i];
manager.didCreate(component);
}
let { updatedComponents, updatedManagers } = this;
for (let i = 0; i < updatedComponents.length; i++) {
let component = updatedComponents[i];
let manager = updatedManagers[i];
manager.didUpdate(component);
}
let { destructors } = this;
for (let i = 0; i < destructors.length; i++) {
destructors[i].destroy();
}
let { scheduledInstallManagers, scheduledInstallModifiers } = this;
for (let i = 0; i < scheduledInstallManagers.length; i++) {
let manager = scheduledInstallManagers[i];
let modifier = scheduledInstallModifiers[i];
manager.install(modifier);
}
let { scheduledUpdateModifierManagers, scheduledUpdateModifiers } = this;
for (let i = 0; i < scheduledUpdateModifierManagers.length; i++) {
let manager = scheduledUpdateModifierManagers[i];
let modifier = scheduledUpdateModifiers[i];
manager.update(modifier);
}
}
}
class Opcode {
constructor(heap) {
this.heap = heap;
this.offset = 0;
}
get type() {
return this.heap.getbyaddr(this.offset);
}
get op1() {
return this.heap.getbyaddr(this.offset + 1);
}
get op2() {
return this.heap.getbyaddr(this.offset + 2);
}
get op3() {
return this.heap.getbyaddr(this.offset + 3);
}
}
exports.Opcode = Opcode;
var TableSlotState;
(function (TableSlotState) {
TableSlotState[TableSlotState["Allocated"] = 0] = "Allocated";
TableSlotState[TableSlotState["Freed"] = 1] = "Freed";
TableSlotState[TableSlotState["Purged"] = 2] = "Purged";
TableSlotState[TableSlotState["Pointer"] = 3] = "Pointer";
})(TableSlotState || (TableSlotState = {}));
class Heap {
constructor() {
this.heap = [];
this.offset = 0;
this.handle = 0;
/**
* layout:
*
* - pointer into heap
* - size
* - freed (0 or 1)
*/
this.table = [];
}
push(item) {
this.heap[this.offset++] = item;
}
getbyaddr(address) {
return this.heap[address];
}
setbyaddr(address, value) {
this.heap[address] = value;
}
malloc() {
this.table.push(this.offset, 0, 0);
let handle = this.handle;
this.handle += 3;
return handle;
}
finishMalloc(handle) {
let start = this.table[handle];
let finish = this.offset;
this.table[handle + 1] = finish - start;
}
size() {
return this.offset;
}
// It is illegal to close over this address, as compaction
// may move it. However, it is legal to use this address
// multiple times between compactions.
getaddr(handle) {
return this.table[handle];
}
gethandle(address) {
this.table.push(address, 0, TableSlotState.Pointer);
let handle = this.handle;
this.handle += 3;
return handle;
}
sizeof(handle) {
if (false) {
return this.table[handle + 1];
}
return -1;
}
free(handle) {
this.table[handle + 2] = 1;
}
compact() {
let compactedSize = 0;
let { table, table: { length }, heap } = this;
for (let i = 0; i < length; i += 3) {
let offset = table[i];
let size = table[i + 1];
let state = table[i + 2];
if (state === TableSlotState.Purged) {
continue;
} else if (state === TableSlotState.Freed) {
// transition to "already freed"
// a good improvement would be to reuse
// these slots
table[i + 2] = 2;
compactedSize += size;
} else if (state === TableSlotState.Allocated) {
for (let j = offset; j <= i + size; j++) {
heap[j - compactedSize] = heap[j];
}
table[i] = offset - compactedSize;
} else if (state === TableSlotState.Pointer) {
table[i] = offset - compactedSize;
}
}
this.offset = this.offset - compactedSize;
}
}
exports.Heap = Heap;
class Program {
constructor() {
this.heap = new Heap();
this._opcode = new Opcode(this.heap);
this.constants = new _constants.Constants();
}
opcode(offset) {
this._opcode.offset = offset;
return this._opcode;
}
}
exports.Program = Program;
class Environment {
constructor({ appendOperations, updateOperations }) {
this._macros = null;
this._transaction = null;
this.program = new Program();
this.appendOperations = appendOperations;
this.updateOperations = updateOperations;
}
toConditionalReference(reference) {
return new _references.ConditionalReference(reference);
}
getAppendOperations() {
return this.appendOperations;
}
getDOM() {
return this.updateOperations;
}
getIdentity(object) {
return (0, _util.ensureGuid)(object) + '';
}
begin() {
(0, _util.assert)(!this._transaction, 'a glimmer transaction was begun, but one already exists. You may have a nested transaction');
this._transaction = new Transaction();
}
get transaction() {
return (0, _util.expect)(this._transaction, 'must be in a transaction');
}
didCreate(component, manager) {
this.transaction.didCreate(component, manager);
}
didUpdate(component, manager) {
this.transaction.didUpdate(component, manager);
}
scheduleInstallModifier(modifier, manager) {
this.transaction.scheduleInstallModifier(modifier, manager);
}
scheduleUpdateModifier(modifier, manager) {
this.transaction.scheduleUpdateModifier(modifier, manager);
}
didDestroy(d) {
this.transaction.didDestroy(d);
}
commit() {
let transaction = this.transaction;
this._transaction = null;
transaction.commit();
}
attributeFor(element, attr, isTrusting, namespace) {
return (0, _attributeManagers.defaultManagers)(element, attr, isTrusting, namespace === undefined ? null : namespace);
}
macros() {
let macros = this._macros;
if (!macros) {
this._macros = macros = this.populateBuiltins();
}
return macros;
}
populateBuiltins() {
return (0, _functions.populateBuiltins)();
}
}
exports.Environment = Environment;
exports.default = Environment;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxpYi9lbnZpcm9ubWVudC5qcyJdLCJuYW1lcyI6WyJTY29wZSIsImNvbnN0cnVjdG9yIiwic2xvdHMiLCJjYWxsZXJTY29wZSIsImV2YWxTY29wZSIsInBhcnRpYWxNYXAiLCJyb290Iiwic2VsZiIsInNpemUiLCJyZWZzIiwiQXJyYXkiLCJpIiwiaW5pdCIsInNpemVkIiwiZ2V0U2VsZiIsImdldCIsImdldFN5bWJvbCIsInN5bWJvbCIsImdldEJsb2NrIiwiZ2V0RXZhbFNjb3BlIiwiZ2V0UGFydGlhbE1hcCIsImJpbmQiLCJ2YWx1ZSIsInNldCIsImJpbmRTZWxmIiwiYmluZFN5bWJvbCIsImJpbmRCbG9jayIsImJpbmRFdmFsU2NvcGUiLCJtYXAiLCJiaW5kUGFydGlhbE1hcCIsImJpbmRDYWxsZXJTY29wZSIsInNjb3BlIiwiZ2V0Q2FsbGVyU2NvcGUiLCJjaGlsZCIsInNsaWNlIiwiaW5kZXgiLCJsZW5ndGgiLCJSYW5nZUVycm9yIiwiVHJhbnNhY3Rpb24iLCJzY2hlZHVsZWRJbnN0YWxsTWFuYWdlcnMiLCJzY2hlZHVsZWRJbnN0YWxsTW9kaWZpZXJzIiwic2NoZWR1bGVkVXBkYXRlTW9kaWZpZXJNYW5hZ2VycyIsInNjaGVkdWxlZFVwZGF0ZU1vZGlmaWVycyIsImNyZWF0ZWRDb21wb25lbnRzIiwiY3JlYXRlZE1hbmFnZXJzIiwidXBkYXRlZENvbXBvbmVudHMiLCJ1cGRhdGVkTWFuYWdlcnMiLCJkZXN0cnVjdG9ycyIsImRpZENyZWF0ZSIsImNvbXBvbmVudCIsIm1hbmFnZXIiLCJwdXNoIiwiZGlkVXBkYXRlIiwic2NoZWR1bGVJbnN0YWxsTW9kaWZpZXIiLCJtb2RpZmllciIsInNjaGVkdWxlVXBkYXRlTW9kaWZpZXIiLCJkaWREZXN0cm95IiwiZCIsImNvbW1pdCIsImRlc3Ryb3kiLCJpbnN0YWxsIiwidXBkYXRlIiwiT3Bjb2RlIiwiaGVhcCIsIm9mZnNldCIsInR5cGUiLCJnZXRieWFkZHIiLCJvcDEiLCJvcDIiLCJvcDMiLCJUYWJsZVNsb3RTdGF0ZSIsIkhlYXAiLCJoYW5kbGUiLCJ0YWJsZSIsIml0ZW0iLCJhZGRyZXNzIiwic2V0YnlhZGRyIiwibWFsbG9jIiwiZmluaXNoTWFsbG9jIiwic3RhcnQiLCJmaW5pc2giLCJnZXRhZGRyIiwiZ2V0aGFuZGxlIiwiUG9pbnRlciIsInNpemVvZiIsImZyZWUiLCJjb21wYWN0IiwiY29tcGFjdGVkU2l6ZSIsInN0YXRlIiwiUHVyZ2VkIiwiRnJlZWQiLCJBbGxvY2F0ZWQiLCJqIiwiUHJvZ3JhbSIsIl9vcGNvZGUiLCJjb25zdGFudHMiLCJvcGNvZGUiLCJFbnZpcm9ubWVudCIsImFwcGVuZE9wZXJhdGlvbnMiLCJ1cGRhdGVPcGVyYXRpb25zIiwiX21hY3JvcyIsIl90cmFuc2FjdGlvbiIsInByb2dyYW0iLCJ0b0NvbmRpdGlvbmFsUmVmZXJlbmNlIiwicmVmZXJlbmNlIiwiZ2V0QXBwZW5kT3BlcmF0aW9ucyIsImdldERPTSIsImdldElkZW50aXR5Iiwib2JqZWN0IiwiYmVnaW4iLCJ0cmFuc2FjdGlvbiIsImF0dHJpYnV0ZUZvciIsImVsZW1lbnQiLCJhdHRyIiwiaXNUcnVzdGluZyIsIm5hbWVzcGFjZSIsInVuZGVmaW5lZCIsIm1hY3JvcyIsInBvcHVsYXRlQnVpbHRpbnMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFFTyxNQUFNQSxLQUFOLENBQVk7QUFDZkM7QUFDQTtBQUNBQyxTQUZBLEVBRU9DLFdBRlA7QUFHQTtBQUNBQyxhQUpBO0FBS0E7QUFDQUMsY0FOQSxFQU1ZO0FBQ1IsYUFBS0gsS0FBTCxHQUFhQSxLQUFiO0FBQ0EsYUFBS0MsV0FBTCxHQUFtQkEsV0FBbkI7QUFDQSxhQUFLQyxTQUFMLEdBQWlCQSxTQUFqQjtBQUNBLGFBQUtDLFVBQUwsR0FBa0JBLFVBQWxCO0FBQ0g7QUFDRCxXQUFPQyxJQUFQLENBQVlDLElBQVosRUFBa0JDLE9BQU8sQ0FBekIsRUFBNEI7QUFDeEIsWUFBSUMsT0FBTyxJQUFJQyxLQUFKLENB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O0FBQ0RDLGFBQVM7QUFDTCxZQUFJb0QsY0FBYyxLQUFLQSxXQUF2QjtBQUNBLGFBQUtULFlBQUwsR0FBb0IsSUFBcEI7QUFDQVMsb0JBQVlwRCxNQUFaO0FBQ0g7QUFDRHFELGlCQUFhQyxPQUFiLEVBQXNCQyxJQUF0QixFQUE0QkMsVUFBNUIsRUFBd0NDLFNBQXhDLEVBQW1EO0FBQy9DLGVBQU8sd0NBQWdCSCxPQUFoQixFQUF5QkMsSUFBekIsRUFBK0JDLFVBQS9CLEVBQTJDQyxjQUFjQyxTQUFkLEdBQTBCLElBQTFCLEdBQWlDRCxTQUE1RSxDQUFQO0FBQ0g7QUFDREUsYUFBUztBQUNMLFlBQUlBLFNBQVMsS0FBS2pCLE9BQWxCO0FBQ0EsWUFBSSxDQUFDaUIsTUFBTCxFQUFhO0FBQ1QsaUJBQUtqQixPQUFMLEdBQWVpQixTQUFTLEtBQUtDLGdCQUFMLEVBQXhCO0FBQ0g7QUFDRCxlQUFPRCxNQUFQO0FBQ0g7QUFDREMsdUJBQW1CO0FBQ2YsZUFBTyxrQ0FBUDtBQUNIO0FBM0RvQjtRQUFackIsVyxHQUFBQSxXO2tCQTZERUEsVyIsImZpbGUiOiJsaWIvZW52aXJvbm1lbnQuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBwb3B1bGF0ZUJ1aWx0aW5zIH0gZnJvbSAnLi9zeW50YXgvZnVuY3Rpb25zJztcbmltcG9ydCB7IENvbnN0YW50cyB9IGZyb20gJy4vZW52aXJvbm1lbnQvY29uc3RhbnRzJztcbmltcG9ydCB7IFVOREVGSU5FRF9SRUZFUkVOQ0UsIENvbmRpdGlvbmFsUmVmZXJlbmNlIH0gZnJvbSAnLi9yZWZlcmVuY2VzJztcbmltcG9ydCB7IGRlZmF1bHRNYW5hZ2VycyB9IGZyb20gJy4vZG9tL2F0dHJpYnV0ZS1tYW5hZ2Vycyc7XG5pbXBvcnQgeyBhc3NlcnQsIGVuc3VyZUd1aWQsIGV4cGVjdCB9IGZyb20gJ0BnbGltbWVyL3V0aWwnO1xuXG5leHBvcnQgY2xhc3MgU2NvcGUge1xuICAgIGNvbnN0cnVjdG9yKFxuICAgIC8vIHRoZSAwdGggc2xvdCBpcyBgc2VsZmBcbiAgICBzbG90cywgY2FsbGVyU2NvcGUsXG4gICAgLy8gbmFtZWQgYXJndW1lbnRzIGFuZCBibG9ja3MgcGFzc2VkIHRvIGEgbGF5b3V0IHRoYXQgdXNlcyBldmFsXG4gICAgZXZhbFNjb3BlLFxuICAgIC8vIGxvY2FscyBpbiBzY29wZSB3aGVuIHRoZSBwYXJ0aWFsIHdhcyBpbnZva2VkXG4gICAgcGFydGlhbE1hcCkge1xuICAgICAgICB0aGlzLnNsb3RzID0gc2xvdHM7XG4gICAgICAgIHRoaXMuY2FsbGVyU2NvcGUgPSBjYWxsZXJTY29wZTtcbiAgICAgICAgdGhpcy5ldmFsU2NvcGUgPSBldmFsU2NvcGU7XG4gICAgICAgIHRoaXMucGFydGlhbE1hcCA9IHBhcnRpYWxNYXA7XG4gICAgfVxuICAgIHN0YXRpYyByb290KHNlbGYsIHNpemUgPSAwKSB7XG4gICAgICAgIGxldCByZWZzID0gbmV3IEFycmF5KHNpemUgKyAxKTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPD0gc2l6ZTsgaSsrKSB7XG4gICAgICAgICAgICByZWZzW2ldID0gVU5ERUZJTkVEX1JFRkVSRU5DRTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3IFNjb3BlKHJlZnMsIG51bGwsIG51bGwsIG51bGwpLmluaXQoeyBzZWxmIH0pO1xuICAgIH1cbiAgICBzdGF0aWMgc2l6ZWQoc2l6ZSA9IDApIHtcbiAgICAgICAgbGV0IHJlZnMgPSBuZXcgQXJyYXkoc2l6ZSArIDEpO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8PSBzaXplOyBpKyspIHtcbiAgICAgICAgICAgIHJlZnNbaV0gPSBVTkRFRklORURfUkVGRVJFTkNFO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBuZXcgU2NvcGUocmVmcywgbnVsbCwgbnVsbCwgbnVsbCk7XG4gICAgfVxuICAgIGluaXQoeyBzZWxmIH0pIHtcbiAgICAgICAgdGhpcy5zbG90c1swXSA9IHNlbGY7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICBnZXRTZWxmKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXQoMCk7XG4gICAgfVxuICAgIGdldFN5bWJvbChzeW1ib2wpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0KHN5bWJvbCk7XG4gICAgfVxuICAgIGdldEJsb2NrKHN5bWJvbCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXQoc3ltYm9sKTtcbiAgICB9XG4gICAgZ2V0RXZhbFNjb3BlKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ldmFsU2NvcGU7XG4gICAgfVxuICAgIGdldFBhcnRpYWxNYXAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnBhcnRpYWxNYXA7XG4gICAgfVxuICAgIGJpbmQoc3ltYm9sLCB2YWx1ZSkge1xuICAgICAgICB0aGlzLnNldChzeW1ib2wsIHZhbHVlKTtcbiAgICB9XG4gICAgYmluZFNlbGYoc2VsZikge1xuICAgICAgICB0aGlzLnNldCgwLCBzZWxmKTtcbiAgICB9XG4gICAgYmluZFN5bWJvbChzeW1ib2wsIHZhbHVlKSB7XG4gICAgICAgIHRoaXMuc2V0KHN5bWJvbCwgdmFsdWUpO1xuICAgIH1cbiAgICBiaW5kQmxvY2soc3ltYm9sLCB2YWx1ZSkge1xuICAgICAgICB0aGlzLnNldChzeW1ib2wsIHZhbHVlKTtcbiAgICB9XG4gICAgYmluZEV2YWxTY29wZShtYXApIHtcbiAgICAgICAgdGhpcy5ldmFsU2NvcGUgPSBtYXA7XG4gICAgfVxuICAgIGJpbmRQYXJ0aWFsTWFwKG1hcCkge1xuICAgICAgICB0aGlzLnBhcnRpYWxNYXAgPSBtYXA7XG4gICAgfVxuICAgIGJpbmRDYWxsZXJTY29wZShzY29wZSkge1xuICAgICAgICB0aGlzLmNhbGxlclNjb3BlID0gc2NvcGU7XG4gICAgfVxuICAgIGdldENhbGxlclNjb3BlKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jYWxsZXJTY29wZTtcbiAgICB9XG4gICAgY2hpbGQoKSB7XG4gICAgICAgIHJldHVybiBuZXcgU2NvcGUodGhpcy5zbG90cy5zbGljZSgpLCB0aGlzLmNhbGxlclNjb3BlLCB0aGlzLmV2YWxTY29wZSwgdGhpcy5wYXJ0aWFsTWFwKTtcbiAgICB9XG4gICAgZ2V0KGluZGV4KSB7XG4gICAgICAgIGlmIChpbmRleCA+PSB0aGlzLnNsb3RzLmxlbmd0aCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoYEJVRzogY2Fubm90IGdldCAkJHtpbmRleH0gZnJvbSBzY29wZTsgbGVuZ3RoPSR7dGhpcy5zbG90cy5sZW5ndGh9YCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuc2xvdHNbaW5kZXhdO1xuICAgIH1cbiAgICBzZXQoaW5kZXgsIHZhbHVlKSB7XG4gICAgICAgIGlmIChpbmRleCA+PSB0aGlzLnNsb3RzLmxlbmd0aCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoYEJVRzogY2Fubm90IGdldCAkJHtpbmRleH0gZnJvbSBzY29wZTsgbGVuZ3RoPSR7dGhpcy5zbG90cy5sZW5ndGh9YCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zbG90c1tpbmRleF0gPSB2YWx1ZTtcbiAgICB9XG59XG5jbGFzcyBUcmFuc2FjdGlvbiB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMuc2NoZWR1bGVkSW5zdGFsbE1hbmFnZXJzID0gW107XG4gICAgICAgIHRoaXMuc2NoZWR1bGVkSW5zdGFsbE1vZGlmaWVycyA9IFtdO1xuICAgICAgICB0aGlzLnNjaGVkdWxlZFVwZGF0ZU1vZGlmaWVyTWFuYWdlcnMgPSBbXTtcbiAgICAgICAgdGhpcy5zY2hlZHVsZWRVcGRhdGVNb2RpZmllcnMgPSBbXTtcbiAgICAgICAgdGhpcy5jcmVhdGVkQ29tcG9uZW50cyA9IFtdO1xuICAgICAgICB0aGlzLmNyZWF0ZWRNYW5hZ2VycyA9IFtdO1xuICAgICAgICB0aGlzLnVwZGF0ZWRDb21wb25lbnRzID0gW107XG4gICAgICAgIHRoaXMudXBkYXRlZE1hbmFnZXJzID0gW107XG4gICAgICAgIHRoaXMuZGVzdHJ1Y3RvcnMgPSBbXTtcbiAgICB9XG4gICAgZGlkQ3JlYXRlKGNvbXBvbmVudCwgbWFuYWdlcikge1xuICAgICAgICB0aGlzLmNyZWF0ZWRDb21wb25lbnRzLnB1c2goY29tcG9uZW50KTtcbiAgICAgICAgdGhpcy5jcmVhdGVkTWFuYWdlcnMucHVzaChtYW5hZ2VyKTtcbiAgICB9XG4gICAgZGlkVXBkYXRlKGNvbXBvbmVudCwgbWFuYWdlcikge1xuICAgICAgICB0aGlzLnVwZGF0ZWRDb21wb25lbnRzLnB1c2goY29tcG9uZW50KTtcbiAgICAgICAgdGhpcy51cGRhdGVkTWFuYWdlcnMucHVzaChtYW5hZ2VyKTtcbiAgICB9XG4gICAgc2NoZWR1bGVJbnN0YWxsTW9kaWZpZXIobW9kaWZpZXIsIG1hbmFnZXIpIHtcbiAgICAgICAgdGhpcy5zY2hlZHVsZWRJbnN0YWxsTWFuYWdlcnMucHVzaChtYW5hZ2VyKTtcbiAgICAgICAgdGhpcy5zY2hlZHVsZWRJbnN0YWxsTW9kaWZpZXJzLnB1c2gobW9kaWZpZXIpO1xuICAgIH1cbiAgICBzY2hlZHVsZVVwZGF0ZU1vZGlmaWVyKG1vZGlmaWVyLCBtYW5hZ2VyKSB7XG4gICAgICAgIHRoaXMuc2NoZWR1bGVkVXBkYXRlTW9kaWZpZXJNYW5hZ2Vycy5wdXNoKG1hbmFnZXIpO1xuICAgICAgICB0aGlzLnNjaGVkdWxlZFVwZGF0ZU1vZGlmaWVycy5wdXNoKG1vZGlmaWVyKTtcbiAgICB9XG4gICAgZGlkRGVzdHJveShkKSB7XG4gICAgICAgIHRoaXMuZGVzdHJ1Y3RvcnMucHVzaChkKTtcbiAgICB9XG4gICAgY29tbWl0KCkge1xuICAgICAgICBsZXQgeyBjcmVhdGVkQ29tcG9uZW50cywgY3JlYXRlZE1hbmFnZXJzIH0gPSB0aGlzO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNyZWF0ZWRDb21wb25lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBsZXQgY29tcG9uZW50ID0gY3JlYXRlZENvbXBvbmVudHNbaV07XG4gICAgICAgICAgICBsZXQgbWFuYWdlciA9IGNyZWF0ZWRNYW5hZ2Vyc1tpXTtcbiAgICAgICAgICAgIG1hbmFnZXIuZGlkQ3JlYXRlKGNvbXBvbmVudCk7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IHsgdXBkYXRlZENvbXBvbmVudHMsIHVwZGF0ZWRNYW5hZ2VycyB9ID0gdGhpcztcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB1cGRhdGVkQ29tcG9uZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgbGV0IGNvbXBvbmVudCA9IHVwZGF0ZWRDb21wb25lbnRzW2ldO1xuICAgICAgICAgICAgbGV0IG1hbmFnZXIgPSB1cGRhdGVkTWFuYWdlcnNbaV07XG4gICAgICAgICAgICBtYW5hZ2VyLmRpZFVwZGF0ZShjb21wb25lbnQpO1xuICAgICAgICB9XG4gICAgICAgIGxldCB7IGRlc3RydWN0b3JzIH0gPSB0aGlzO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGRlc3RydWN0b3JzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBkZXN0cnVjdG9yc1tpXS5kZXN0cm95KCk7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IHsgc2NoZWR1bGVkSW5zdGFsbE1hbmFnZXJzLCBzY2hlZHVsZWRJbnN0YWxsTW9kaWZpZXJzIH0gPSB0aGlzO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNjaGVkdWxlZEluc3RhbGxNYW5hZ2Vycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgbGV0IG1hbmFnZXIgPSBzY2hlZHVsZWRJbnN0YWxsTWFuYWdlcnNbaV07XG4gICAgICAgICAgICBsZXQgbW9kaWZpZXIgPSBzY2hlZHVsZWRJbnN0YWxsTW9kaWZpZXJzW2ldO1xuICAgICAgICAgICAgbWFuYWdlci5pbnN0YWxsKG1vZGlmaWVyKTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgeyBzY2hlZHVsZWRVcGRhdGVNb2RpZmllck1hbmFnZXJzLCBzY2hlZHVsZWRVcGRhdGVNb2RpZmllcnMgfSA9IHRoaXM7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2NoZWR1bGVkVXBkYXRlTW9kaWZpZXJNYW5hZ2Vycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgbGV0IG1hbmFnZXIgPSBzY2hlZHVsZWRVcGRhdGVNb2RpZmllck1hbmFnZXJzW2ldO1xuICAgICAgICAgICAgbGV0IG1vZGlmaWVyID0gc2NoZWR1bGVkVXBkYXRlTW9kaWZpZXJzW2ldO1xuICAgICAgICAgICAgbWFuYWdlci51cGRhdGUobW9kaWZpZXIpO1xuICAgICAgICB9XG4gICAgfVxufVxuZXhwb3J0IGNsYXNzIE9wY29kZSB7XG4gICAgY29uc3RydWN0b3IoaGVhcCkge1xuICAgICAgICB0aGlzLmhlYXAgPSBoZWFwO1xuICAgICAgICB0aGlzLm9mZnNldCA9IDA7XG4gICAgfVxuICAgIGdldCB0eXBlKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5oZWFwLmdldGJ5YWRkcih0aGlzLm9mZnNldCk7XG4gICAgfVxuICAgIGdldCBvcDEoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmhlYXAuZ2V0YnlhZGRyKHRoaXMub2Zmc2V0ICsgMSk7XG4gICAgfVxuICAgIGdldCBvcDIoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmhlYXAuZ2V0YnlhZGRyKHRoaXMub2Zmc2V0ICsgMik7XG4gICAgfVxuICAgIGdldCBvcDMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmhlYXAuZ2V0YnlhZGRyKHRoaXMub2Zmc2V0ICsgMyk7XG4gICAgfVxufVxudmFyIFRhYmxlU2xvdFN0YXRlO1xuKGZ1bmN0aW9uIChUYWJsZVNsb3RTdGF0ZSkge1xuICAgIFRhYmxlU2xvdFN0YXRlW1RhYmxlU2xvdFN0YXRlW1wiQWxsb2NhdGVkXCJdID0gMF0gPSBcIkFsbG9jYXRlZFwiO1xuICAgIFRhYmxlU2xvdFN0YXRlW1RhYmxlU2xvdFN0YXRlW1wiRnJlZWRcIl0gPSAxXSA9IFwiRnJlZWRcIjtcbiAgICBUYWJsZVNsb3RTdGF0ZVtUYWJsZVNsb3RTdGF0ZVtcIlB1cmdlZFwiXSA9IDJdID0gXCJQdXJnZWRcIjtcbiAgICBUYWJsZVNsb3RTdGF0ZVtUYWJsZVNsb3RTdGF0ZVtcIlBvaW50ZXJcIl0gPSAzXSA9IFwiUG9pbnRlclwiO1xufSkoVGFibGVTbG90U3RhdGUgfHwgKFRhYmxlU2xvdFN0YXRlID0ge30pKTtcbmV4cG9ydCBjbGFzcyBIZWFwIHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhpcy5oZWFwID0gW107XG4gICAgICAgIHRoaXMub2Zmc2V0ID0gMDtcbiAgICAgICAgdGhpcy5oYW5kbGUgPSAwO1xuICAgICAgICAvKipcbiAgICAgICAgICogbGF5b3V0OlxuICAgICAgICAgKlxuICAgICAgICAgKiAtIHBvaW50ZXIgaW50byBoZWFwXG4gICAgICAgICAqIC0gc2l6ZVxuICAgICAgICAgKiAtIGZyZWVkICgwIG9yIDEpXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLnRhYmxlID0gW107XG4gICAgfVxuICAgIHB1c2goaXRlbSkge1xuICAgICAgICB0aGlzLmhlYXBbdGhpcy5vZmZzZXQrK10gPSBpdGVtO1xuICAgIH1cbiAgICBnZXRieWFkZHIoYWRkcmVzcykge1xuICAgICAgICByZXR1cm4gdGhpcy5oZWFwW2FkZHJlc3NdO1xuICAgIH1cbiAgICBzZXRieWFkZHIoYWRkcmVzcywgdmFsdWUpIHtcbiAgICAgICAgdGhpcy5oZWFwW2FkZHJlc3NdID0gdmFsdWU7XG4gICAgfVxuICAgIG1hbGxvYygpIHtcbiAgICAgICAgdGhpcy50YWJsZS5wdXNoKHRoaXMub2Zmc2V0LCAwLCAwKTtcbiAgICAgICAgbGV0IGhhbmRsZSA9IHRoaXMuaGFuZGxlO1xuICAgICAgICB0aGlzLmhhbmRsZSArPSAzO1xuICAgICAgICByZXR1cm4gaGFuZGxlO1xuICAgIH1cbiAgICBmaW5pc2hNYWxsb2MoaGFuZGxlKSB7XG4gICAgICAgIGxldCBzdGFydCA9IHRoaXMudGFibGVbaGFuZGxlXTtcbiAgICAgICAgbGV0IGZpbmlzaCA9IHRoaXMub2Zmc2V0O1xuICAgICAgICB0aGlzLnRhYmxlW2hhbmRsZSArIDFdID0gZmluaXNoIC0gc3RhcnQ7XG4gICAgfVxuICAgIHNpemUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm9mZnNldDtcbiAgICB9XG4gICAgLy8gSXQgaXMgaWxsZWdhbCB0byBjbG9zZSBvdmVyIHRoaXMgYWRkcmVzcywgYXMgY29tcGFjdGlvblxuICAgIC8vIG1heSBtb3ZlIGl0LiBIb3dldmVyLCBpdCBpcyBsZWdhbCB0byB1c2UgdGhpcyBhZGRyZXNzXG4gICAgLy8gbXVsdGlwbGUgdGltZXMgYmV0d2VlbiBjb21wYWN0aW9ucy5cbiAgICBnZXRhZGRyKGhhbmRsZSkge1xuICAgICAgICByZXR1cm4gdGhpcy50YWJsZVtoYW5kbGVdO1xuICAgIH1cbiAgICBnZXRoYW5kbGUoYWRkcmVzcykge1xuICAgICAgICB0aGlzLnRhYmxlLnB1c2goYWRkcmVzcywgMCwgVGFibGVTbG90U3RhdGUuUG9pbnRlcik7XG4gICAgICAgIGxldCBoYW5kbGUgPSB0aGlzLmhhbmRsZTtcbiAgICAgICAgdGhpcy5oYW5kbGUgKz0gMztcbiAgICAgICAgcmV0dXJuIGhhbmRsZTtcbiAgICB9XG4gICAgc2l6ZW9mKGhhbmRsZSkge1xuICAgICAgICBpZiAoZmFsc2UpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnRhYmxlW2hhbmRsZSArIDFdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAtMTtcbiAgICB9XG4gICAgZnJlZShoYW5kbGUpIHtcbiAgICAgICAgdGhpcy50YWJsZVtoYW5kbGUgKyAyXSA9IDE7XG4gICAgfVxuICAgIGNvbXBhY3QoKSB7XG4gICAgICAgIGxldCBjb21wYWN0ZWRTaXplID0gMDtcbiAgICAgICAgbGV0IHsgdGFibGUsIHRhYmxlOiB7IGxlbmd0aCB9LCBoZWFwIH0gPSB0aGlzO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgaSArPSAzKSB7XG4gICAgICAgICAgICBsZXQgb2Zmc2V0ID0gdGFibGVbaV07XG4gICAgICAgICAgICBsZXQgc2l6ZSA9IHRhYmxlW2kgKyAxXTtcbiAgICAgICAgICAgIGxldCBzdGF0ZSA9IHRhYmxlW2kgKyAyXTtcbiAgICAgICAgICAgIGlmIChzdGF0ZSA9PT0gVGFibGVTbG90U3RhdGUuUHVyZ2VkKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHN0YXRlID09PSBUYWJsZVNsb3RTdGF0ZS5GcmVlZCkge1xuICAgICAgICAgICAgICAgIC8vIHRyYW5zaXRpb24gdG8gXCJhbHJlYWR5IGZyZWVkXCJcbiAgICAgICAgICAgICAgICAvLyBhIGdvb2QgaW1wcm92ZW1lbnQgd291bGQgYmUgdG8gcmV1c2VcbiAgICAgICAgICAgICAgICAvLyB0aGVzZSBzbG90c1xuICAgICAgICAgICAgICAgIHRhYmxlW2kgKyAyXSA9IDI7XG4gICAgICAgICAgICAgICAgY29tcGFjdGVkU2l6ZSArPSBzaXplO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChzdGF0ZSA9PT0gVGFibGVTbG90U3RhdGUuQWxsb2NhdGVkKSB7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IG9mZnNldDsgaiA8PSBpICsgc2l6ZTsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIGhlYXBbaiAtIGNvbXBhY3RlZFNpemVdID0gaGVhcFtqXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGFibGVbaV0gPSBvZmZzZXQgLSBjb21wYWN0ZWRTaXplO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChzdGF0ZSA9PT0gVGFibGVTbG90U3RhdGUuUG9pbnRlcikge1xuICAgICAgICAgICAgICAgIHRhYmxlW2ldID0gb2Zmc2V0IC0gY29tcGFjdGVkU2l6ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLm9mZnNldCA9IHRoaXMub2Zmc2V0IC0gY29tcGFjdGVkU2l6ZTtcbiAgICB9XG59XG5leHBvcnQgY2xhc3MgUHJvZ3JhbSB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMuaGVhcCA9IG5ldyBIZWFwKCk7XG4gICAgICAgIHRoaXMuX29wY29kZSA9IG5ldyBPcGNvZGUodGhpcy5oZWFwKTtcbiAgICAgICAgdGhpcy5jb25zdGFudHMgPSBuZXcgQ29uc3RhbnRzKCk7XG4gICAgfVxuICAgIG9wY29kZShvZmZzZXQpIHtcbiAgICAgICAgdGhpcy5fb3Bjb2RlLm9mZnNldCA9IG9mZnNldDtcbiAgICAgICAgcmV0dXJuIHRoaXMuX29wY29kZTtcbiAgICB9XG59XG5leHBvcnQgY2xhc3MgRW52aXJvbm1lbnQge1xuICAgIGNvbnN0cnVjdG9yKHsgYXBwZW5kT3BlcmF0aW9ucywgdXBkYXRlT3BlcmF0aW9ucyB9KSB7XG4gICAgICAgIHRoaXMuX21hY3JvcyA9IG51bGw7XG4gICAgICAgIHRoaXMuX3RyYW5zYWN0aW9uID0gbnVsbDtcbiAgICAgICAgdGhpcy5wcm9ncmFtID0gbmV3IFByb2dyYW0oKTtcbiAgICAgICAgdGhpcy5hcHBlbmRPcGVyYXRpb25zID0gYXBwZW5kT3BlcmF0aW9ucztcbiAgICAgICAgdGhpcy51cGRhdGVPcGVyYXRpb25zID0gdXBkYXRlT3BlcmF0aW9ucztcbiAgICB9XG4gICAgdG9Db25kaXRpb25hbFJlZmVyZW5jZShyZWZlcmVuY2UpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBDb25kaXRpb25hbFJlZmVyZW5jZShyZWZlcmVuY2UpO1xuICAgIH1cbiAgICBnZXRBcHBlbmRPcGVyYXRpb25zKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5hcHBlbmRPcGVyYXRpb25zO1xuICAgIH1cbiAgICBnZXRET00oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnVwZGF0ZU9wZXJhdGlvbnM7XG4gICAgfVxuICAgIGdldElkZW50aXR5KG9iamVjdCkge1xuICAgICAgICByZXR1cm4gZW5zdXJlR3VpZChvYmplY3QpICsgJyc7XG4gICAgfVxuICAgIGJlZ2luKCkge1xuICAgICAgICBhc3NlcnQoIXRoaXMuX3RyYW5zYWN0aW9uLCAnYSBnbGltbWVyIHRyYW5zYWN0aW9uIHdhcyBiZWd1biwgYnV0IG9uZSBhbHJlYWR5IGV4aXN0cy4gWW91IG1heSBoYXZlIGEgbmVzdGVkIHRyYW5zYWN0aW9uJyk7XG4gICAgICAgIHRoaXMuX3RyYW5zYWN0aW9uID0gbmV3IFRyYW5zYWN0aW9uKCk7XG4gICAgfVxuICAgIGdldCB0cmFuc2FjdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIGV4cGVjdCh0aGlzLl90cmFuc2FjdGlvbiwgJ211c3QgYmUgaW4gYSB0cmFuc2FjdGlvbicpO1xuICAgIH1cbiAgICBkaWRDcmVhdGUoY29tcG9uZW50LCBtYW5hZ2VyKSB7XG4gICAgICAgIHRoaXMudHJhbnNhY3Rpb24uZGlkQ3JlYXRlKGNvbXBvbmVudCwgbWFuYWdlcik7XG4gICAgfVxuICAgIGRpZFVwZGF0ZShjb21wb25lbnQsIG1hbmFnZXIpIHtcbiAgICAgICAgdGhpcy50cmFuc2FjdGlvbi5kaWRVcGRhdGUoY29tcG9uZW50LCBtYW5hZ2VyKTtcbiAgICB9XG4gICAgc2NoZWR1bGVJbnN0YWxsTW9kaWZpZXIobW9kaWZpZXIsIG1hbmFnZXIpIHtcbiAgICAgICAgdGhpcy50cmFuc2FjdGlvbi5zY2hlZHVsZUluc3RhbGxNb2RpZmllcihtb2RpZmllciwgbWFuYWdlcik7XG4gICAgfVxuICAgIHNjaGVkdWxlVXBkYXRlTW9kaWZpZXIobW9kaWZpZXIsIG1hbmFnZXIpIHtcbiAgICAgICAgdGhpcy50cmFuc2FjdGlvbi5zY2hlZHVsZVVwZGF0ZU1vZGlmaWVyKG1vZGlmaWVyLCBtYW5hZ2VyKTtcbiAgICB9XG4gICAgZGlkRGVzdHJveShkKSB7XG4gICAgICAgIHRoaXMudHJhbnNhY3Rpb24uZGlkRGVzdHJveShkKTtcbiAgICB9XG4gICAgY29tbWl0KCkge1xuICAgICAgICBsZXQgdHJhbnNhY3Rpb24gPSB0aGlzLnRyYW5zYWN0aW9uO1xuICAgICAgICB0aGlzLl90cmFuc2FjdGlvbiA9IG51bGw7XG4gICAgICAgIHRyYW5zYWN0aW9uLmNvbW1pdCgpO1xuICAgIH1cbiAgICBhdHRyaWJ1dGVGb3IoZWxlbWVudCwgYXR0ciwgaXNUcnVzdGluZywgbmFtZXNwYWNlKSB7XG4gICAgICAgIHJldHVybiBkZWZhdWx0TWFuYWdlcnMoZWxlbWVudCwgYXR0ciwgaXNUcnVzdGluZywgbmFtZXNwYWNlID09PSB1bmRlZmluZWQgPyBudWxsIDogbmFtZXNwYWNlKTtcbiAgICB9XG4gICAgbWFjcm9zKCkge1xuICAgICAgICBsZXQgbWFjcm9zID0gdGhpcy5fbWFjcm9zO1xuICAgICAgICBpZiAoIW1hY3Jvcykge1xuICAgICAgICAgICAgdGhpcy5fbWFjcm9zID0gbWFjcm9zID0gdGhpcy5wb3B1bGF0ZUJ1aWx0aW5zKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG1hY3JvcztcbiAgICB9XG4gICAgcG9wdWxhdGVCdWlsdGlucygpIHtcbiAgICAgICAgcmV0dXJuIHBvcHVsYXRlQnVpbHRpbnMoKTtcbiAgICB9XG59XG5leHBvcnQgZGVmYXVsdCBFbnZpcm9ubWVudDsiXX0=