reign
Version:
A persistent, typed-objects implementation.
172 lines (136 loc) • 5.07 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.Realm = undefined;
var _bluebird = require("bluebird");
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 }; }
const HEADER_ADDRESS = 336; // First usable block in the backing store.
const VERSION_ADDRESS = HEADER_ADDRESS;
const STRING_POOL_POINTER_ADDRESS = VERSION_ADDRESS + 8;
const ROOT_MAP_POINTER_ADDRESS = STRING_POOL_POINTER_ADDRESS + 8;
const HEADER_CHECKSUM_ADDRESS = ROOT_MAP_POINTER_ADDRESS + 8;
const HEADER_SIZE = HEADER_CHECKSUM_ADDRESS + 8 - HEADER_ADDRESS;
const FIRST_ADDRESS = HEADER_ADDRESS + HEADER_SIZE;
const $RootHashMap = Symbol('%RootHashMap');
class Realm {
constructor(backing) {
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.
*/
init() {
var _this = this;
return (0, _bluebird.coroutine)(function* () {
if (_this.isInitialized) {
throw new Error(`Realm cannot be initialized twice.`);
}
if (!_this.backing.isInitialized) {
yield _this.backing.init();
}
verifyHeader(_this);
_this.strings = (0, _stringPool.make)(_this, STRING_POOL_POINTER_ADDRESS);
(0, _builtins.registerBuiltins)(_this);
let 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 _this;
})();
}
/**
* Return the type of the given value.
*/
typeOf(value) {
// Issue 252
if (value == null || typeof value === 'function' || 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;
}
}
get(key) {
// Issue 252
return this[$RootHashMap].get(key);
}
has(key) {
// Issue 252
return this[$RootHashMap].has(key);
}
set(key, value) {
// Issue 252
this[$RootHashMap].set(key, value);
return this;
}
delete(key) {
// Issue 252
return this[$RootHashMap].delete(key);
}
}
exports.Realm = Realm;
function verifyHeader(realm) {
const backing = realm.backing;
if (backing.getUint32(HEADER_ADDRESS) !== HEADER_ADDRESS || backing.getUint32(HEADER_CHECKSUM_ADDRESS) !== HEADER_CHECKSUM_ADDRESS) {
const 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);
}
}