UNPKG

reign

Version:

A persistent, typed-objects implementation.

238 lines (209 loc) 7.49 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MIN_TYPE_ID = undefined; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; exports. /** * Makes a UnionType type class for the given realm. */ make = make; var _backing = require("backing"); var _backing2 = _interopRequireDefault(_backing); var _ = require("../"); var _util = require("../../util"); var _2 = require("../../"); var _symbols = require("../../symbols"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } var MIN_TYPE_ID = exports.MIN_TYPE_ID = Math.pow(2, 20) * 8;function make(realm) { var TypeClass = realm.TypeClass; var typeCounter = 0; return new TypeClass('UnionType', function () { for (var _len = arguments.length, possibleTypes = Array(_len), _key = 0; _key < _len; _key++) { possibleTypes[_key] = arguments[_key]; } return function (Union) { typeCounter++; var name = possibleTypes.map(function (PossibleType) { return PossibleType.name; }).join(' | '); var id = MIN_TYPE_ID + typeCounter; Union[_symbols.$CanBeEmbedded] = true; Union[_symbols.$CanBeReferenced] = false; Union[_symbols.$CanContainReferences] = possibleTypes.some(function (type) { return type[_symbols.$CanContainReferences]; }); var byteAlignment = Math.max.apply(Math, [4].concat(_toConsumableArray(possibleTypes.map(function (type) { return type.byteAlignment; })))); var byteLength = (0, _util.alignTo)(Math.max.apply(Math, _toConsumableArray(possibleTypes.map(function (type) { return type.byteLength; }))) + 4, byteAlignment); var idOffset = byteLength - 4; var UnionArray = void 0; // Issue 285 Object.defineProperties(Union, { Array: { get: function get() { if (UnionArray === undefined) { UnionArray = new realm.ArrayType(Union); } return UnionArray; } } }); var prototype = Object.create(null, { // Issue 285 value: { enumerable: true, get: function get() { var backing = this[_symbols.$Backing]; var address = this[_symbols.$Address]; var typeId = backing.getUint32(address + idOffset); if (typeId === 0) { return null; } else { return realm.I[typeId].load(backing, address); } }, set: function set(value) { var backing = this[_symbols.$Backing]; var address = this[_symbols.$Address]; storeUnion(backing, address, value); } }, // Issue 285 type: { enumerable: true, get: function get() { var typeId = this[_symbols.$Backing].getUint32(this[_symbols.$Address] + idOffset); return typeId === 0 ? null : realm.I[typeId]; } }, inspect: { value: function value() { return this.value; } }, valueOf: { value: function value() { return this.value; } }, toJSON: { value: function value() { var value = this.value; if (value != null && (typeof value === "undefined" ? "undefined" : _typeof(value)) === 'object' && typeof value.toJSON === 'function') { return value.toJSON(); } else { return value; } } } }); function constructor(backingOrInput, address) { if (backingOrInput instanceof _backing2.default) { this[_symbols.$Backing] = backingOrInput; this[_symbols.$Address] = address; } else { var backing = realm.backing; this[_symbols.$Backing] = backing; this[_symbols.$Address] = backing.gc.alloc(byteLength, Union.id); initializeUnion(backing, this[_symbols.$Address], backingOrInput); } } function unionAccepts(input) { for (var i = 0; i < possibleTypes.length; i++) { var type = possibleTypes[i]; if (type.accepts(input)) { return true; } } return false; } function initializeUnion(backing, address, initialValue) { if (initialValue == null) { backing.setUint32(address + idOffset, 0); } else { var type = typeFor(initialValue); type.initialize(backing, address, initialValue); backing.setUint32(address + idOffset, type.id); } } function storeUnion(backing, address, value) { var existing = backing.getUint32(address + idOffset); if (existing !== 0) { realm.I[existing].clear(backing, address); } else if (value == null) { // nothing to do. return; } if (value == null) { backing.setUint32(address + idOffset, 0); } else { var type = typeFor(value); type.initialize(backing, address, value); backing.setUint32(address + idOffset, type.id); } } function loadUnion(backing, address) { var typeId = backing.getUint32(address + idOffset); if (typeId === 0) { return null; } else { return realm.I[typeId].load(backing, address); } } function clearUnion(backing, address) { var typeId = backing.getUint32(address + idOffset); if (typeId !== 0) { backing.setUint32(backing, address + idOffset, 0); realm.I[typeId].clear(backing, address); } } function unionDestructor(backing, address) { var typeId = backing.getUint32(address + idOffset); if (typeId !== 0) { realm.I[typeId].clear(backing, address); } } function typeFor(input) { for (var i = 0; i < possibleTypes.length; i++) { var type = possibleTypes[i]; if (type.accepts(input)) { return type; } } throw new TypeError("Union does not contain a type which can accept the given input."); } return { id: id, name: name, byteLength: byteLength, byteAlignment: byteAlignment, constructor: constructor, prototype: prototype, accepts: unionAccepts, initialize: initializeUnion, store: storeUnion, load: loadUnion, clear: clearUnion, destructor: unionDestructor, equal: function equal(a, b) { return typeFor(a).equal(a, b); }, emptyValue: function emptyValue() { return null; }, randomValue: function randomValue() { return possibleTypes[Math.floor(Math.random() * possibleTypes.length)].randomValue(); }, hashValue: function hashValue(input) { return typeFor(input).hashValue(input); } }; }; }); };