reign
Version:
A persistent, typed-objects implementation.
217 lines (172 loc) • 7.75 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.Realm = 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; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _typeClass = require("./type-class");
var _primitiveType = require("./type-class/primitive-type");
var _stringType = require("./type-class/string-type");
var _referenceType = require("./type-class/reference-type");
var _structType = require("./type-class/struct-type");
var _objectType = require("./type-class/object-type");
var _arrayType = require("./type-class/array-type");
var _hashMapType = require("./type-class/hash-map-type");
var _hashSetType = require("./type-class/hash-set-type");
var _unionType = require("./type-class/union-type");
var _enumType = require("./type-class/enum-type");
var _stringPool = require("./string-pool");
var _builtins = require("./builtins");
var _backing = require("backing");
var _backing2 = _interopRequireDefault(_backing);
var _typeRegistry = require("type-registry");
var _typeRegistry2 = _interopRequireDefault(_typeRegistry);
var _symbols = require("./symbols");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { return step("next", value); }, function (err) { return step("throw", err); }); } } return step("next"); }); }; }
var HEADER_ADDRESS = 336; // First usable block in the backing store.
var VERSION_ADDRESS = HEADER_ADDRESS;
var STRING_POOL_POINTER_ADDRESS = VERSION_ADDRESS + 8;
var ROOT_MAP_POINTER_ADDRESS = STRING_POOL_POINTER_ADDRESS + 8;
var HEADER_CHECKSUM_ADDRESS = ROOT_MAP_POINTER_ADDRESS + 8;
var HEADER_SIZE = HEADER_CHECKSUM_ADDRESS + 8 - HEADER_ADDRESS;
var FIRST_ADDRESS = HEADER_ADDRESS + HEADER_SIZE;
var $RootHashMap = Symbol('%RootHashMap');
var Realm = exports.Realm = function () {
function Realm(backing) {
_classCallCheck(this, Realm);
this.backing = backing;
this.registry = backing.registry;
this.T = this.registry.T;
this.I = this.registry.I;
this.TypeClass = (0, _typeClass.make)(this);
this.PrimitiveType = (0, _primitiveType.make)(this);
this.ReferenceType = (0, _referenceType.make)(this);
this.StructType = (0, _structType.make)(this);
this.ObjectType = (0, _objectType.make)(this);
this.ArrayType = (0, _arrayType.make)(this);
this.StringType = (0, _stringType.make)(this);
this.HashMapType = (0, _hashMapType.make)(this);
this.HashSetType = (0, _hashSetType.make)(this);
this.UnionType = (0, _unionType.make)(this);
this.EnumType = (0, _enumType.make)(this);
this.isInitialized = false;
}
/**
* Initialize the realm.
*/
_createClass(Realm, [{
key: "init",
value: function init() {
var _this2 = this;
var _this = this;
return _asyncToGenerator(regeneratorRuntime.mark(function _callee() {
var rootAddress;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
if (!_this.isInitialized) {
_context.next = 2;
break;
}
throw new Error("Realm cannot be initialized twice.");
case 2:
if (_this.backing.isInitialized) {
_context.next = 5;
break;
}
_context.next = 5;
return _this.backing.init();
case 5:
verifyHeader(_this);
_this.strings = (0, _stringPool.make)(_this, STRING_POOL_POINTER_ADDRESS);
(0, _builtins.registerBuiltins)(_this);
rootAddress = _this.backing.getFloat64(ROOT_MAP_POINTER_ADDRESS);
if (rootAddress === 0) {
// Issue 252
_this[$RootHashMap] = new _this.T.HashMap();
// Issue 252
_this.backing.setFloat64(ROOT_MAP_POINTER_ADDRESS, _this[$RootHashMap][_symbols.$Address]);
} else {
// Issue 252
_this[$RootHashMap] = new _this.T.HashMap(_this.backing, rootAddress);
}
_this.isInitialized = true;
Object.freeze(_this);
return _context.abrupt("return", _this);
case 13:
case "end":
return _context.stop();
}
}
}, _callee, _this2);
}))();
}
/**
* Return the type of the given value.
*/
}, {
key: "typeOf",
value: function typeOf(value) {
// Issue 252
if (value == null || typeof value === 'function' || (typeof value === "undefined" ? "undefined" : _typeof(value)) === 'symbol') {
return null;
} else if (typeof value === 'number') {
return this.T.Float64;
} else if (typeof value === 'boolean') {
return this.T.Boolean;
} else if (typeof value === 'string') {
return this.T.String;
} else if (value[_symbols.$ValueType]) {
return value[_symbols.$ValueType];
} else if (Array.isArray(value)) {
return this.T.Array;
} else {
return this.T.Object;
}
}
}, {
key: "get",
value: function get(key) {
// Issue 252
return this[$RootHashMap].get(key);
}
}, {
key: "has",
value: function has(key) {
// Issue 252
return this[$RootHashMap].has(key);
}
}, {
key: "set",
value: function set(key, value) {
// Issue 252
this[$RootHashMap].set(key, value);
return this;
}
}, {
key: "delete",
value: function _delete(key) {
// Issue 252
return this[$RootHashMap].delete(key);
}
}]);
return Realm;
}();
function verifyHeader(realm) {
var backing = realm.backing;
if (backing.getUint32(HEADER_ADDRESS) !== HEADER_ADDRESS || backing.getUint32(HEADER_CHECKSUM_ADDRESS) !== HEADER_CHECKSUM_ADDRESS) {
var address = backing.calloc(HEADER_SIZE);
/* istanbul ignore if */
if (address !== HEADER_ADDRESS) {
throw new TypeError("Allocator returned an invalid backing header address, got " + address + " expected " + HEADER_ADDRESS + ".");
}
backing.setUint32(HEADER_ADDRESS, HEADER_ADDRESS);
backing.setUint32(HEADER_CHECKSUM_ADDRESS, HEADER_CHECKSUM_ADDRESS);
backing.setFloat64(STRING_POOL_POINTER_ADDRESS, 0);
backing.setFloat64(ROOT_MAP_POINTER_ADDRESS, 0);
}
}