Lee Thanh
Upload 3012 files
5641073
raw
history blame
5.29 kB
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Orphan = void 0;
const tslib_1 = require("tslib");
const debug_1 = tslib_1.__importDefault(require("debug"));
const errors_1 = require("../../errors");
const util_1 = require("../../util");
const list_element_size_1 = require("../list-element-size");
const object_size_1 = require("../object-size");
const pointer_1 = require("./pointer");
const pointer_type_1 = require("./pointer-type");
const trace = debug_1.default("capnp:orphan");
trace("load");
// Technically speaking this class doesn't need to be generic, but the extra type checking enforced by this helps to
// make sure you don't accidentally adopt a pointer of the wrong type.
/**
* An orphaned pointer. This object itself is technically a pointer to the original pointer's content, which was left
* untouched in its original message. The original pointer data is encoded as attributes on the Orphan object, ready to
* be reconstructed once another pointer is ready to adopt it.
*
* @export
* @class Orphan
* @extends {Pointer}
* @template T
*/
class Orphan {
constructor(src) {
const c = pointer_1.getContent(src);
this.segment = c.segment;
this.byteOffset = c.byteOffset;
this._capnp = {};
// Read vital info from the src pointer so we can reconstruct it during adoption.
this._capnp.type = pointer_1.getTargetPointerType(src);
switch (this._capnp.type) {
case pointer_type_1.PointerType.STRUCT:
this._capnp.size = pointer_1.getTargetStructSize(src);
break;
case pointer_type_1.PointerType.LIST:
this._capnp.length = pointer_1.getTargetListLength(src);
this._capnp.elementSize = pointer_1.getTargetListElementSize(src);
if (this._capnp.elementSize === list_element_size_1.ListElementSize.COMPOSITE) {
this._capnp.size = pointer_1.getTargetCompositeListSize(src);
}
break;
case pointer_type_1.PointerType.OTHER:
this._capnp.capId = pointer_1.getCapabilityId(src);
break;
default:
// COVERAGE: Unreachable code.
/* istanbul ignore next */
throw new Error(errors_1.PTR_INVALID_POINTER_TYPE);
}
// Zero out the source pointer (but not the contents!).
pointer_1.erasePointer(src);
}
/**
* Adopt (move) this orphan into the target pointer location. This will allocate far pointers in `dst` as needed.
*
* @param {T} dst The destination pointer.
* @returns {void}
*/
_moveTo(dst) {
if (this._capnp === undefined) {
throw new Error(util_1.format(errors_1.PTR_ALREADY_ADOPTED, this));
}
// TODO: Implement copy semantics when this happens.
if (this.segment.message !== dst.segment.message) {
throw new Error(util_1.format(errors_1.PTR_ADOPT_WRONG_MESSAGE, this, dst));
}
// Recursively wipe out the destination pointer first.
pointer_1.erase(dst);
const res = pointer_1.initPointer(this.segment, this.byteOffset, dst);
switch (this._capnp.type) {
case pointer_type_1.PointerType.STRUCT:
pointer_1.setStructPointer(res.offsetWords, this._capnp.size, res.pointer);
break;
case pointer_type_1.PointerType.LIST: {
let offsetWords = res.offsetWords;
if (this._capnp.elementSize === list_element_size_1.ListElementSize.COMPOSITE) {
offsetWords--; // The tag word gets skipped.
}
pointer_1.setListPointer(offsetWords, this._capnp.elementSize, this._capnp.length, res.pointer, this._capnp.size);
break;
}
case pointer_type_1.PointerType.OTHER:
pointer_1.setInterfacePointer(this._capnp.capId, res.pointer);
break;
/* istanbul ignore next */
default:
throw new Error(errors_1.PTR_INVALID_POINTER_TYPE);
}
this._capnp = undefined;
}
dispose() {
// FIXME: Should this throw?
if (this._capnp === undefined) {
trace("not disposing an already disposed orphan", this);
return;
}
switch (this._capnp.type) {
case pointer_type_1.PointerType.STRUCT:
this.segment.fillZeroWords(this.byteOffset, object_size_1.getWordLength(this._capnp.size));
break;
case pointer_type_1.PointerType.LIST: {
const byteLength = pointer_1.getListByteLength(this._capnp.elementSize, this._capnp.length, this._capnp.size);
this.segment.fillZeroWords(this.byteOffset, byteLength);
break;
}
default:
// Other pointer types don't actually have any content.
break;
}
this._capnp = undefined;
}
toString() {
return util_1.format("Orphan_%d@%a,type:%s", this.segment.id, this.byteOffset, this._capnp && this._capnp.type);
}
}
exports.Orphan = Orphan;
//# sourceMappingURL=orphan.js.map