UNPKG

tlo

Version:

Reader of binary serialized Type Language Schema

1,771 lines (1,446 loc) 47.2 kB
import * as fs from 'fs'; /*! ***************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ /* global Reflect, Promise */ var extendStatics = function(d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; function __extends(d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } var global = (typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}); /** * If `Buffer.TYPED_ARRAY_SUPPORT`: * === true Use Uint8Array implementation (fastest) * === false Use Object implementation (most compatible, even IE6) * * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, * Opera 11.6+, iOS 4.2+. * * Due to various browser bugs, sometimes the Object implementation will be used even * when the browser supports typed arrays. * * Note: * * - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances, * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438. * * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function. * * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of * incorrect length in some situations. * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they * get the Object implementation, which is slower but behaves correctly. */ global.TYPED_ARRAY_SUPPORT !== undefined ? global.TYPED_ARRAY_SUPPORT : true; // the following is from is-buffer, also by Feross Aboukhadijeh and with same lisence // The _isBuffer check is for Safari 5-7 support, because it's missing // Object.prototype.constructor. Remove this eventually function isBuffer(obj) { return obj != null && (!!obj._isBuffer || isFastBuffer(obj) || isSlowBuffer(obj)) } function isFastBuffer (obj) { return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj) } // For Node v0.10 support. Remove this eventually. function isSlowBuffer (obj) { return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isFastBuffer(obj.slice(0, 0)) } var inherits; if (typeof Object.create === 'function'){ inherits = function inherits(ctor, superCtor) { // implementation from standard node.js 'util' module ctor.super_ = superCtor; ctor.prototype = Object.create(superCtor.prototype, { constructor: { value: ctor, enumerable: false, writable: true, configurable: true } }); }; } else { inherits = function inherits(ctor, superCtor) { ctor.super_ = superCtor; var TempCtor = function () {}; TempCtor.prototype = superCtor.prototype; ctor.prototype = new TempCtor(); ctor.prototype.constructor = ctor; }; } var inherits$1 = inherits; /** * Echos the value of a value. Trys to print the value out * in the best way possible given the different types. * * @param {Object} obj The object to print out. * @param {Object} opts Optional options object that alters the output. */ /* legacy: obj, showHidden, depth, colors*/ function inspect$1(obj, opts) { // default options var ctx = { seen: [], stylize: stylizeNoColor }; // legacy... if (arguments.length >= 3) ctx.depth = arguments[2]; if (arguments.length >= 4) ctx.colors = arguments[3]; if (isBoolean(opts)) { // legacy... ctx.showHidden = opts; } else if (opts) { // got an "options" object _extend(ctx, opts); } // set default options if (isUndefined(ctx.showHidden)) ctx.showHidden = false; if (isUndefined(ctx.depth)) ctx.depth = 2; if (isUndefined(ctx.colors)) ctx.colors = false; if (isUndefined(ctx.customInspect)) ctx.customInspect = true; if (ctx.colors) ctx.stylize = stylizeWithColor; return formatValue(ctx, obj, ctx.depth); } // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics inspect$1.colors = { 'bold' : [1, 22], 'italic' : [3, 23], 'underline' : [4, 24], 'inverse' : [7, 27], 'white' : [37, 39], 'grey' : [90, 39], 'black' : [30, 39], 'blue' : [34, 39], 'cyan' : [36, 39], 'green' : [32, 39], 'magenta' : [35, 39], 'red' : [31, 39], 'yellow' : [33, 39] }; // Don't use 'blue' not visible on cmd.exe inspect$1.styles = { 'special': 'cyan', 'number': 'yellow', 'boolean': 'yellow', 'undefined': 'grey', 'null': 'bold', 'string': 'green', 'date': 'magenta', // "name": intentionally not styling 'regexp': 'red' }; function stylizeWithColor(str, styleType) { var style = inspect$1.styles[styleType]; if (style) { return '\u001b[' + inspect$1.colors[style][0] + 'm' + str + '\u001b[' + inspect$1.colors[style][1] + 'm'; } else { return str; } } function stylizeNoColor(str, styleType) { return str; } function arrayToHash(array) { var hash = {}; array.forEach(function(val, idx) { hash[val] = true; }); return hash; } function formatValue(ctx, value, recurseTimes) { // Provide a hook for user-specified inspect functions. // Check that value is an object with an inspect function on it if (ctx.customInspect && value && isFunction(value.inspect) && // Filter out the util module, it's inspect function is special value.inspect !== inspect$1 && // Also filter out any prototype objects using the circular check. !(value.constructor && value.constructor.prototype === value)) { var ret = value.inspect(recurseTimes, ctx); if (!isString(ret)) { ret = formatValue(ctx, ret, recurseTimes); } return ret; } // Primitive types cannot have properties var primitive = formatPrimitive(ctx, value); if (primitive) { return primitive; } // Look up the keys of the object. var keys = Object.keys(value); var visibleKeys = arrayToHash(keys); if (ctx.showHidden) { keys = Object.getOwnPropertyNames(value); } // IE doesn't make error fields non-enumerable // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx if (isError(value) && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { return formatError(value); } // Some type of object without properties can be shortcutted. if (keys.length === 0) { if (isFunction(value)) { var name = value.name ? ': ' + value.name : ''; return ctx.stylize('[Function' + name + ']', 'special'); } if (isRegExp(value)) { return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); } if (isDate(value)) { return ctx.stylize(Date.prototype.toString.call(value), 'date'); } if (isError(value)) { return formatError(value); } } var base = '', array = false, braces = ['{', '}']; // Make Array say that they are Array if (isArray(value)) { array = true; braces = ['[', ']']; } // Make functions say that they are functions if (isFunction(value)) { var n = value.name ? ': ' + value.name : ''; base = ' [Function' + n + ']'; } // Make RegExps say that they are RegExps if (isRegExp(value)) { base = ' ' + RegExp.prototype.toString.call(value); } // Make dates with properties first say the date if (isDate(value)) { base = ' ' + Date.prototype.toUTCString.call(value); } // Make error with message first say the error if (isError(value)) { base = ' ' + formatError(value); } if (keys.length === 0 && (!array || value.length == 0)) { return braces[0] + base + braces[1]; } if (recurseTimes < 0) { if (isRegExp(value)) { return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); } else { return ctx.stylize('[Object]', 'special'); } } ctx.seen.push(value); var output; if (array) { output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); } else { output = keys.map(function(key) { return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); }); } ctx.seen.pop(); return reduceToSingleString(output, base, braces); } function formatPrimitive(ctx, value) { if (isUndefined(value)) return ctx.stylize('undefined', 'undefined'); if (isString(value)) { var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') .replace(/'/g, "\\'") .replace(/\\"/g, '"') + '\''; return ctx.stylize(simple, 'string'); } if (isNumber(value)) return ctx.stylize('' + value, 'number'); if (isBoolean(value)) return ctx.stylize('' + value, 'boolean'); // For some reason typeof null is "object", so special case here. if (isNull(value)) return ctx.stylize('null', 'null'); } function formatError(value) { return '[' + Error.prototype.toString.call(value) + ']'; } function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { var output = []; for (var i = 0, l = value.length; i < l; ++i) { if (hasOwnProperty(value, String(i))) { output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, String(i), true)); } else { output.push(''); } } keys.forEach(function(key) { if (!key.match(/^\d+$/)) { output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, key, true)); } }); return output; } function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { var name, str, desc; desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; if (desc.get) { if (desc.set) { str = ctx.stylize('[Getter/Setter]', 'special'); } else { str = ctx.stylize('[Getter]', 'special'); } } else { if (desc.set) { str = ctx.stylize('[Setter]', 'special'); } } if (!hasOwnProperty(visibleKeys, key)) { name = '[' + key + ']'; } if (!str) { if (ctx.seen.indexOf(desc.value) < 0) { if (isNull(recurseTimes)) { str = formatValue(ctx, desc.value, null); } else { str = formatValue(ctx, desc.value, recurseTimes - 1); } if (str.indexOf('\n') > -1) { if (array) { str = str.split('\n').map(function(line) { return ' ' + line; }).join('\n').substr(2); } else { str = '\n' + str.split('\n').map(function(line) { return ' ' + line; }).join('\n'); } } } else { str = ctx.stylize('[Circular]', 'special'); } } if (isUndefined(name)) { if (array && key.match(/^\d+$/)) { return str; } name = JSON.stringify('' + key); if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { name = name.substr(1, name.length - 2); name = ctx.stylize(name, 'name'); } else { name = name.replace(/'/g, "\\'") .replace(/\\"/g, '"') .replace(/(^"|"$)/g, "'"); name = ctx.stylize(name, 'string'); } } return name + ': ' + str; } function reduceToSingleString(output, base, braces) { var length = output.reduce(function(prev, cur) { if (cur.indexOf('\n') >= 0) ; return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; }, 0); if (length > 60) { return braces[0] + (base === '' ? '' : base + '\n ') + ' ' + output.join(',\n ') + ' ' + braces[1]; } return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; } // NOTE: These type checking functions intentionally don't use `instanceof` // because it is fragile and can be easily faked with `Object.create()`. function isArray(ar) { return Array.isArray(ar); } function isBoolean(arg) { return typeof arg === 'boolean'; } function isNull(arg) { return arg === null; } function isNumber(arg) { return typeof arg === 'number'; } function isString(arg) { return typeof arg === 'string'; } function isUndefined(arg) { return arg === void 0; } function isRegExp(re) { return isObject(re) && objectToString(re) === '[object RegExp]'; } function isObject(arg) { return typeof arg === 'object' && arg !== null; } function isDate(d) { return isObject(d) && objectToString(d) === '[object Date]'; } function isError(e) { return isObject(e) && (objectToString(e) === '[object Error]' || e instanceof Error); } function isFunction(arg) { return typeof arg === 'function'; } function isPrimitive(arg) { return arg === null || typeof arg === 'boolean' || typeof arg === 'number' || typeof arg === 'string' || typeof arg === 'symbol' || // ES6 symbol typeof arg === 'undefined'; } function objectToString(o) { return Object.prototype.toString.call(o); } function _extend(origin, add) { // Don't do anything if add isn't an object if (!add || !isObject(add)) return origin; var keys = Object.keys(add); var i = keys.length; while (i--) { origin[keys[i]] = add[keys[i]]; } return origin; } function hasOwnProperty(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } function compare(a, b) { if (a === b) { return 0; } var x = a.length; var y = b.length; for (var i = 0, len = Math.min(x, y); i < len; ++i) { if (a[i] !== b[i]) { x = a[i]; y = b[i]; break; } } if (x < y) { return -1; } if (y < x) { return 1; } return 0; } var hasOwn = Object.prototype.hasOwnProperty; var objectKeys = Object.keys || function (obj) { var keys = []; for (var key in obj) { if (hasOwn.call(obj, key)) keys.push(key); } return keys; }; var pSlice = Array.prototype.slice; var _functionsHaveNames; function functionsHaveNames() { if (typeof _functionsHaveNames !== 'undefined') { return _functionsHaveNames; } return _functionsHaveNames = (function () { return function foo() {}.name === 'foo'; }()); } function pToString (obj) { return Object.prototype.toString.call(obj); } function isView(arrbuf) { if (isBuffer(arrbuf)) { return false; } if (typeof global.ArrayBuffer !== 'function') { return false; } if (typeof ArrayBuffer.isView === 'function') { return ArrayBuffer.isView(arrbuf); } if (!arrbuf) { return false; } if (arrbuf instanceof DataView) { return true; } if (arrbuf.buffer && arrbuf.buffer instanceof ArrayBuffer) { return true; } return false; } // 1. The assert module provides functions that throw // AssertionError's when particular conditions are not met. The // assert module must conform to the following interface. function assert(value, message) { if (!value) fail(value, true, message, '==', ok); } // 2. The AssertionError is defined in assert. // new assert.AssertionError({ message: message, // actual: actual, // expected: expected }) var regex = /\s*function\s+([^\(\s]*)\s*/; // based on https://github.com/ljharb/function.prototype.name/blob/adeeeec8bfcc6068b187d7d9fb3d5bb1d3a30899/implementation.js function getName(func) { if (!isFunction(func)) { return; } if (functionsHaveNames()) { return func.name; } var str = func.toString(); var match = str.match(regex); return match && match[1]; } assert.AssertionError = AssertionError; function AssertionError(options) { this.name = 'AssertionError'; this.actual = options.actual; this.expected = options.expected; this.operator = options.operator; if (options.message) { this.message = options.message; this.generatedMessage = false; } else { this.message = getMessage(this); this.generatedMessage = true; } var stackStartFunction = options.stackStartFunction || fail; if (Error.captureStackTrace) { Error.captureStackTrace(this, stackStartFunction); } else { // non v8 browsers so we can have a stacktrace var err = new Error(); if (err.stack) { var out = err.stack; // try to strip useless frames var fn_name = getName(stackStartFunction); var idx = out.indexOf('\n' + fn_name); if (idx >= 0) { // once we have located the function frame // we need to strip out everything before it (and its line) var next_line = out.indexOf('\n', idx + 1); out = out.substring(next_line + 1); } this.stack = out; } } } // assert.AssertionError instanceof Error inherits$1(AssertionError, Error); function truncate(s, n) { if (typeof s === 'string') { return s.length < n ? s : s.slice(0, n); } else { return s; } } function inspect(something) { if (functionsHaveNames() || !isFunction(something)) { return inspect$1(something); } var rawname = getName(something); var name = rawname ? ': ' + rawname : ''; return '[Function' + name + ']'; } function getMessage(self) { return truncate(inspect(self.actual), 128) + ' ' + self.operator + ' ' + truncate(inspect(self.expected), 128); } // At present only the three keys mentioned above are used and // understood by the spec. Implementations or sub modules can pass // other keys to the AssertionError's constructor - they will be // ignored. // 3. All of the following functions must throw an AssertionError // when a corresponding condition is not met, with a message that // may be undefined if not provided. All assertion methods provide // both the actual and expected values to the assertion error for // display purposes. function fail(actual, expected, message, operator, stackStartFunction) { throw new AssertionError({ message: message, actual: actual, expected: expected, operator: operator, stackStartFunction: stackStartFunction }); } // EXTENSION! allows for well behaved errors defined elsewhere. assert.fail = fail; // 4. Pure assertion tests whether a value is truthy, as determined // by !!guard. // assert.ok(guard, message_opt); // This statement is equivalent to assert.equal(true, !!guard, // message_opt);. To test strictly for the value true, use // assert.strictEqual(true, guard, message_opt);. function ok(value, message) { if (!value) fail(value, true, message, '==', ok); } assert.ok = ok; // 5. The equality assertion tests shallow, coercive equality with // ==. // assert.equal(actual, expected, message_opt); assert.equal = equal; function equal(actual, expected, message) { if (actual != expected) fail(actual, expected, message, '==', equal); } // 6. The non-equality assertion tests for whether two objects are not equal // with != assert.notEqual(actual, expected, message_opt); assert.notEqual = notEqual; function notEqual(actual, expected, message) { if (actual == expected) { fail(actual, expected, message, '!=', notEqual); } } // 7. The equivalence assertion tests a deep equality relation. // assert.deepEqual(actual, expected, message_opt); assert.deepEqual = deepEqual; function deepEqual(actual, expected, message) { if (!_deepEqual(actual, expected, false)) { fail(actual, expected, message, 'deepEqual', deepEqual); } } assert.deepStrictEqual = deepStrictEqual; function deepStrictEqual(actual, expected, message) { if (!_deepEqual(actual, expected, true)) { fail(actual, expected, message, 'deepStrictEqual', deepStrictEqual); } } function _deepEqual(actual, expected, strict, memos) { // 7.1. All identical values are equivalent, as determined by ===. if (actual === expected) { return true; } else if (isBuffer(actual) && isBuffer(expected)) { return compare(actual, expected) === 0; // 7.2. If the expected value is a Date object, the actual value is // equivalent if it is also a Date object that refers to the same time. } else if (isDate(actual) && isDate(expected)) { return actual.getTime() === expected.getTime(); // 7.3 If the expected value is a RegExp object, the actual value is // equivalent if it is also a RegExp object with the same source and // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`). } else if (isRegExp(actual) && isRegExp(expected)) { return actual.source === expected.source && actual.global === expected.global && actual.multiline === expected.multiline && actual.lastIndex === expected.lastIndex && actual.ignoreCase === expected.ignoreCase; // 7.4. Other pairs that do not both pass typeof value == 'object', // equivalence is determined by ==. } else if ((actual === null || typeof actual !== 'object') && (expected === null || typeof expected !== 'object')) { return strict ? actual === expected : actual == expected; // If both values are instances of typed arrays, wrap their underlying // ArrayBuffers in a Buffer each to increase performance // This optimization requires the arrays to have the same type as checked by // Object.prototype.toString (aka pToString). Never perform binary // comparisons for Float*Arrays, though, since e.g. +0 === -0 but their // bit patterns are not identical. } else if (isView(actual) && isView(expected) && pToString(actual) === pToString(expected) && !(actual instanceof Float32Array || actual instanceof Float64Array)) { return compare(new Uint8Array(actual.buffer), new Uint8Array(expected.buffer)) === 0; // 7.5 For all other Object pairs, including Array objects, equivalence is // determined by having the same number of owned properties (as verified // with Object.prototype.hasOwnProperty.call), the same set of keys // (although not necessarily the same order), equivalent values for every // corresponding key, and an identical 'prototype' property. Note: this // accounts for both named and indexed properties on Arrays. } else if (isBuffer(actual) !== isBuffer(expected)) { return false; } else { memos = memos || {actual: [], expected: []}; var actualIndex = memos.actual.indexOf(actual); if (actualIndex !== -1) { if (actualIndex === memos.expected.indexOf(expected)) { return true; } } memos.actual.push(actual); memos.expected.push(expected); return objEquiv(actual, expected, strict, memos); } } function isArguments(object) { return Object.prototype.toString.call(object) == '[object Arguments]'; } function objEquiv(a, b, strict, actualVisitedObjects) { if (a === null || a === undefined || b === null || b === undefined) return false; // if one is a primitive, the other must be same if (isPrimitive(a) || isPrimitive(b)) return a === b; if (strict && Object.getPrototypeOf(a) !== Object.getPrototypeOf(b)) return false; var aIsArgs = isArguments(a); var bIsArgs = isArguments(b); if ((aIsArgs && !bIsArgs) || (!aIsArgs && bIsArgs)) return false; if (aIsArgs) { a = pSlice.call(a); b = pSlice.call(b); return _deepEqual(a, b, strict); } var ka = objectKeys(a); var kb = objectKeys(b); var key, i; // having the same number of owned properties (keys incorporates // hasOwnProperty) if (ka.length !== kb.length) return false; //the same set of keys (although not necessarily the same order), ka.sort(); kb.sort(); //~~~cheap key test for (i = ka.length - 1; i >= 0; i--) { if (ka[i] !== kb[i]) return false; } //equivalent values for every corresponding key, and //~~~possibly expensive deep test for (i = ka.length - 1; i >= 0; i--) { key = ka[i]; if (!_deepEqual(a[key], b[key], strict, actualVisitedObjects)) return false; } return true; } // 8. The non-equivalence assertion tests for any deep inequality. // assert.notDeepEqual(actual, expected, message_opt); assert.notDeepEqual = notDeepEqual; function notDeepEqual(actual, expected, message) { if (_deepEqual(actual, expected, false)) { fail(actual, expected, message, 'notDeepEqual', notDeepEqual); } } assert.notDeepStrictEqual = notDeepStrictEqual; function notDeepStrictEqual(actual, expected, message) { if (_deepEqual(actual, expected, true)) { fail(actual, expected, message, 'notDeepStrictEqual', notDeepStrictEqual); } } // 9. The strict equality assertion tests strict equality, as determined by ===. // assert.strictEqual(actual, expected, message_opt); assert.strictEqual = strictEqual; function strictEqual(actual, expected, message) { if (actual !== expected) { fail(actual, expected, message, '===', strictEqual); } } // 10. The strict non-equality assertion tests for strict inequality, as // determined by !==. assert.notStrictEqual(actual, expected, message_opt); assert.notStrictEqual = notStrictEqual; function notStrictEqual(actual, expected, message) { if (actual === expected) { fail(actual, expected, message, '!==', notStrictEqual); } } function expectedException(actual, expected) { if (!actual || !expected) { return false; } if (Object.prototype.toString.call(expected) == '[object RegExp]') { return expected.test(actual); } try { if (actual instanceof expected) { return true; } } catch (e) { // Ignore. The instanceof check doesn't work for arrow functions. } if (Error.isPrototypeOf(expected)) { return false; } return expected.call({}, actual) === true; } function _tryBlock(block) { var error; try { block(); } catch (e) { error = e; } return error; } function _throws(shouldThrow, block, expected, message) { var actual; if (typeof block !== 'function') { throw new TypeError('"block" argument must be a function'); } if (typeof expected === 'string') { message = expected; expected = null; } actual = _tryBlock(block); message = (expected && expected.name ? ' (' + expected.name + ').' : '.') + (message ? ' ' + message : '.'); if (shouldThrow && !actual) { fail(actual, expected, 'Missing expected exception' + message); } var userProvidedMessage = typeof message === 'string'; var isUnwantedException = !shouldThrow && isError(actual); var isUnexpectedException = !shouldThrow && actual && !expected; if ((isUnwantedException && userProvidedMessage && expectedException(actual, expected)) || isUnexpectedException) { fail(actual, expected, 'Got unwanted exception' + message); } if ((shouldThrow && actual && expected && !expectedException(actual, expected)) || (!shouldThrow && actual)) { throw actual; } } // 11. Expected to throw an error: // assert.throws(block, Error_opt, message_opt); assert.throws = throws; function throws(block, /*optional*/error, /*optional*/message) { _throws(true, block, error, message); } // EXTENSION! This is annoying to write outside this module. assert.doesNotThrow = doesNotThrow; function doesNotThrow(block, /*optional*/error, /*optional*/message) { _throws(false, block, error, message); } assert.ifError = ifError; function ifError(err) { if (err) throw err; } var NODE_TYPE_TYPE = 1; var NODE_TYPE_NAT_CONST = 2; var NODE_TYPE_VAR_TYPE = 3; var NODE_TYPE_VAR_NUM = 4; var NODE_TYPE_ARRAY = 5; var FLAG_NOVAR = 1 << 21; var FLAG_BARE = 1 << 0; var TlBase = function () { function TlBase() {} return TlBase; }(); var Arg = function (_super) { __extends(Arg, _super); function Arg(name, flags, var_num, exist_var_num, exist_var_bit, type) { var _this = _super.call(this) || this; _this.name = name; _this.flags = flags || 0; _this.var_num = var_num; _this.exist_var_num = exist_var_num; _this.exist_var_bit = exist_var_bit; _this.type = type; return _this; } return Arg; }(TlBase); var TlCombinator = function (_super) { __extends(TlCombinator, _super); function TlCombinator(id, name, var_count, type_id, args, result) { var _this = _super.call(this) || this; _this.id = id; _this.name = name; _this.var_count = var_count || 0; _this.type_id = type_id || 0; _this.args = args; _this.result = result; return _this; } return TlCombinator; }(TlBase); var TlType = function (_super) { __extends(TlType, _super); function TlType(id, name, arity, flags, simple_constructors, constructors_num, constructors) { var _this = _super.call(this) || this; _this.add_constructor = function (new_constructor) { if (_this.constructors) { _this.constructors.push(new_constructor); } }; _this.id = id; _this.name = name; _this.arity = arity; _this.flags = flags || 0; _this.simple_constructors = simple_constructors; _this.constructors_num = constructors_num; _this.constructors = constructors; return _this; } return TlType; }(TlBase); var TlTree = function (_super) { __extends(TlTree, _super); function TlTree(flags) { var _this = _super.call(this) || this; _this.get_type = function () { throw new Error("Not Implemented"); }; _this.flags = flags; return _this; } return TlTree; }(TlBase); var TlTreeType = function (_super) { __extends(TlTreeType, _super); function TlTreeType(flags, type) { var _this = _super.call(this, flags) || this; _this.get_type = function () { return NODE_TYPE_TYPE; }; _this.type = type; _this.children = []; return _this; } return TlTreeType; }(TlTree); var TlTreeNatConst = function (_super) { __extends(TlTreeNatConst, _super); function TlTreeNatConst(flags, num) { var _this = _super.call(this, flags) || this; _this.get_type = function () { return NODE_TYPE_NAT_CONST; }; _this.num = num; return _this; } return TlTreeNatConst; }(TlTree); var TlTreeVarType = function (_super) { __extends(TlTreeVarType, _super); function TlTreeVarType(flags, var_num) { var _this = _super.call(this, flags) || this; _this.get_type = function () { return NODE_TYPE_VAR_TYPE; }; _this.var_num = var_num; return _this; } return TlTreeVarType; }(TlTree); var TlTreeVarNum = function (_super) { __extends(TlTreeVarNum, _super); function TlTreeVarNum(flags, var_num, diff) { var _this = _super.call(this, flags) || this; _this.get_type = function () { return NODE_TYPE_VAR_NUM; }; _this.var_num = var_num; _this.diff = diff; return _this; } return TlTreeVarNum; }(TlTree); var TlTreeArray = function (_super) { __extends(TlTreeArray, _super); function TlTreeArray(flags, multiplicity, a) { var _this = _super.call(this, flags) || this; _this.get_type = function () { return NODE_TYPE_ARRAY; }; _this.multiplicity = multiplicity; _this.args = a; return _this; } return TlTreeArray; }(TlTree); var TlConfig = function (_super) { __extends(TlConfig, _super); function TlConfig() { var _this = _super.call(this) || this; _this.add_type = function (type) { if (type.id && type.name) { _this.types.push(type); _this.id_to_type[type.id] = type; _this.name_to_type[type.name] = type; } }; _this.get_type = function (type_id_or_name) { if (typeof type_id_or_name == 'number') { return _this.id_to_type[type_id_or_name]; } else { return _this.name_to_type[type_id_or_name]; } }; _this.add_function = function (func) { if (func.id && func.name) { _this.functions.push(func); _this.id_to_function[func.id] = func; _this.name_to_function[func.name] = func; } }; _this.get_function = function (function_id_or_name) { if (typeof function_id_or_name == 'number') { return _this.id_to_function[function_id_or_name]; } else { return _this.name_to_function[function_id_or_name]; } }; _this.get_type_count = function () { return _this.types.length; }; _this.get_type_by_num = function (num) { return _this.types[num]; }; _this.get_function_count = function () { return _this.functions.length; }; _this.get_function_by_num = function (num) { return _this.functions[num]; }; _this.types = []; _this.id_to_type = {}; _this.name_to_type = {}; _this.functions = []; _this.id_to_function = {}; _this.name_to_function = {}; return _this; } return TlConfig; }(TlBase); var get_array_buffer = function (data) { var ab = new ArrayBuffer(data.length); var view = new Uint8Array(ab); for (var i = 0; i < data.length; ++i) { view[i] = data[i]; } return ab; }; var TlSimpleParser = function () { function TlSimpleParser(data) { var _this = this; this.set_error = function (error_message) { if (_this.error != null) { assert(error_message != null); _this.error = error_message; _this.error_pos = _this.data_begin_len - _this.offset; _this.data = new ArrayBuffer(8); _this.data_len = 0; } else { _this.data = new ArrayBuffer(8); assert(_this.data_len == 0); } }; this.check_len = function (len) { if (_this.data_len < len) { _this.set_error('Not enough data to read'); } else { _this.data_len -= len; } }; this.get_error = function () { return _this.error; }; this.get_error_pos = function () { return _this.error_pos; }; this.fetch_int = function () { _this.check_len(4 /* SIZE_OF_INT32 */ ); var result = new DataView(_this.data, _this.offset).getUint32(0, true); _this.offset += 4 /* SIZE_OF_INT32 */ ; return result; }; this.fetch_long = function () { _this.check_len(8 /* SIZE_OF_INT64 */ ); var result = new DataView(_this.data, _this.offset).getBigUint64(0, true); _this.offset += 8 /* SIZE_OF_INT64 */ ; return result; }; this.unpack_uchar = function (offset) { if (offset === void 0) { offset = 0; } return new DataView(_this.data, _this.offset + offset).getInt8(0); }; this.fetch_string = function () { _this.check_len(4); var result_len = _this.unpack_uchar(); if (result_len < 254) { _this.check_len((result_len >> 2) * 4); var result = []; var data_view = new DataView(_this.data, _this.offset + 1 /* SIZE_OF_INT8 */ * 1); for (var i = 0; i < result_len; i++) { result.push(data_view.getInt8(1 /* SIZE_OF_INT8 */ * i)); } var result_decoded = result.map(function (e) { return String.fromCharCode(e); }); _this.offset += ((result_len >> 2) + 1) * 4; return result_decoded.join(''); } if (result_len == 254) { var result_len_1 = _this.unpack_uchar(1) + (_this.unpack_uchar(2) << 8) + (_this.unpack_uchar(3) << 16); _this.check_len((result_len_1 + 3 >> 2) * 4); var result = []; var data_view = new DataView(_this.data, _this.offset + 1 /* SIZE_OF_INT8 */ * 4); for (var i = 0; i < result_len_1; i++) { result.push(data_view.getInt8(1 /* SIZE_OF_INT8 */ * i)); } var result_decoded = result.map(function (e) { return String.fromCharCode(e); }); _this.offset += (result_len_1 + 7 >> 2) * 4; return result_decoded.join(''); } _this.set_error('Can\'t fetch string, 255 found'); return ''; }; this.fetch_end = function () { if (_this.data_len) { _this.set_error('Too much data to fetch'); } }; this.data = get_array_buffer(data); this.data_begin_len = data.length; this.data_len = data.length; this.offset = 0; this.error = ''; this.error_pos = 0; } return TlSimpleParser; }(); var TLS_SCHEMA_V2 = 0x3A2F9BE2; var TLS_SCHEMA_V3 = 0xE4A8604B; var TLS_SCHEMA_V4 = 0x90AC88D7; var TLS_TYPE = 0x12EB4386; var TLS_COMBINATOR = 0x5C0A1ED5; var TLS_COMBINATOR_LEFT_BUILTIN = 0xCD211F63; var TLS_COMBINATOR_LEFT = 0x4C12C6D9; var TLS_COMBINATOR_RIGHT_V2 = 0x2C064372; var TLS_ARG_V2 = 0x29DFE61B; var TLS_EXPR_NAT = 0xDCB49BD8; var TLS_EXPR_TYPE = 0xECC9DA78; var TLS_NAT_CONST_OLD = 0xDCB49BD8; var TLS_NAT_CONST = 0x8CE940B1; var TLS_NAT_VAR = 0x4E8A14F0; var TLS_TYPE_VAR = 0x0142CEAE; var TLS_ARRAY = 0xD9FB20DE; var TLS_TYPE_EXPR = 0xC1863D08; var TlConfigParser = function (_super) { __extends(TlConfigParser, _super); function TlConfigParser(data) { var _this = _super.call(this) || this; _this.parse_config = function () { _this.schema_version = _this.get_schema_version(_this.try_parse_int()); if (_this.schema_version < 2) { throw Error("Unsupported tl-schema version " + _this.schema_version); } _this.try_parse_int(); // date _this.try_parse_int(); // version var types_n = _this.try_parse_int(); var constructors_total = 0; for (var i = 0; i < types_n; i++) { var tl_type = _this.read_type(); _this.config.add_type(tl_type); constructors_total += tl_type.constructors_num || 0; } var constructors_n = _this.try_parse_int(); assert(constructors_n == constructors_total); for (var i = 0; i < constructors_n; i++) { var tl_combinator = _this.read_combinator(); _this.config.get_type(tl_combinator.type_id).add_constructor(tl_combinator); } var functions_n = _this.try_parse_int(); for (var i = 0; i < functions_n; i++) { _this.config.add_function(_this.read_combinator()); } _this.p.fetch_end(); _this.try_parse(0); return _this.config; }; _this.get_schema_version = function (version_id) { switch (version_id) { case TLS_SCHEMA_V4: { return 4; } case TLS_SCHEMA_V3: { return 3; } case TLS_SCHEMA_V2: { return 2; } default: { return -1; } } }; _this.read_type = function () { var t = _this.try_parse_int(); if (t != TLS_TYPE) { throw Error("Wrong tls_type magic " + t); } var tl_type = new TlType(); tl_type.id = _this.try_parse_int(); tl_type.name = _this.try_parse_string(); tl_type.constructors_num = _this.try_parse_int(); tl_type.constructors = []; tl_type.flags = _this.try_parse_int(); tl_type.flags &= ~(1 | 8 | 16 | 1024); if (tl_type.flags != 0) { throw Error("Type " + tl_type.name + " has non-zero flags: " + tl_type.flags); } tl_type.arity = _this.try_parse_int(); _this.try_parse_long(); // unused return tl_type; }; _this.read_combinator = function () { var t = _this.try_parse_int(); if (t != TLS_COMBINATOR) { throw Error("Wrong tls_combinator magic " + t); } var tl_combinator = new TlCombinator(); tl_combinator.id = _this.try_parse_int(); tl_combinator.name = _this.try_parse_string(); tl_combinator.type_id = _this.try_parse_int(); tl_combinator.var_count = 0; var left_type = _this.try_parse_int(); if (left_type == TLS_COMBINATOR_LEFT) { tl_combinator.args = _this.read_args_list(tl_combinator); } else { if (left_type != TLS_COMBINATOR_LEFT_BUILTIN) { throw Error("Wrong tls_combinator_left magic " + left_type); } } var right_ver = _this.try_parse_int(); if (right_ver != TLS_COMBINATOR_RIGHT_V2) { throw Error("'Wrong tls_combinator_right magic " + right_ver); } tl_combinator.result = _this.read_type_expr(tl_combinator); return tl_combinator; }; _this.read_num_const = function () { var num = _this.try_parse_int(); return new TlTreeNatConst(FLAG_NOVAR, num); }; _this.read_num_var = function (tl_combinator) { var diff = _this.try_parse_int(); var var_num = _this.try_parse_int(); if (var_num >= tl_combinator.var_count) { tl_combinator.var_count = var_num + 1; } return new TlTreeVarNum(0, var_num, diff); }; _this.read_nat_expr = function (tl_combinator) { var tree_type = _this.try_parse_int(); switch (tree_type) { case TLS_NAT_CONST_OLD: case TLS_NAT_CONST: { return _this.read_num_const(); } case TLS_NAT_VAR: { return _this.read_num_var(tl_combinator); } default: { throw Error("tree_type = " + tree_type); } } }; _this.read_expr = function (tl_combinator) { var tree_type = _this.try_parse_int(); switch (tree_type) { case TLS_EXPR_NAT: { return _this.read_nat_expr(tl_combinator); } case TLS_EXPR_TYPE: { return _this.read_type_expr(tl_combinator); } default: { throw Error("tree_type = " + tree_type); } } }; _this.read_args_list = function (tl_combinator) { var schema_flag_opt_field = 2 << (_this.schema_version >= 3 ? 1 : 0); var schema_flag_has_vars = schema_flag_opt_field ^ 6; var args_num = _this.try_parse_int(); var args_list = []; for (var i = 0; i < args_num; i++) { var arg = new Arg(); var arg_v = _this.try_parse_int(); if (arg_v != TLS_ARG_V2) { throw Error("Wrong tls_arg magic " + arg_v); } arg.name = _this.try_parse_string(); arg.flags = _this.try_parse_int(); var is_optional = false; if (arg.flags & schema_flag_opt_field) { arg.flags &= ~schema_flag_opt_field; is_optional = true; } if (arg.flags & schema_flag_has_vars) { arg.flags &= ~schema_flag_has_vars; arg.var_num = _this.try_parse_int(); } else { arg.var_num = -1; } if (arg.var_num >= tl_combinator.var_count) { tl_combinator.var_count = arg.var_num + 1; } if (is_optional) { arg.exist_var_num = _this.try_parse_int(); arg.exist_var_bit = _this.try_parse_int(); } else { arg.exist_var_num = -1; arg.exist_var_bit = 0; } arg.type = _this.read_type_expr(tl_combinator); if (arg.type.flags & FLAG_NOVAR) { arg.flags |= FLAG_NOVAR; } args_list.push(arg); } return args_list; }; _this.read_type_expr = function (tl_combinator) { var tree_type = _this.try_parse_int(); switch (tree_type) { case TLS_TYPE_VAR: { return _this.read_type_var(tl_combinator); } case TLS_TYPE_EXPR: { return _this.read_type_tree(tl_combinator); } case TLS_ARRAY: { return _this.read_array(tl_combinator); } default: { throw Error("tree_type = " + tree_type); } } }; _this.read_type_var = function (tl_combinator) { var var_num = _this.try_parse_int(); var flags = _this.try_parse_int(); if (var_num >= tl_combinator.var_count) { tl_combinator.var_count = var_num + 1; } assert(!(flags & (FLAG_NOVAR | FLAG_BARE))); return new TlTreeVarType(flags, var_num); }; _this.read_type_tree = function (tl_combinator) { var tl_type = _this.config.get_type(_this.try_parse_int()); assert(tl_type != undefined); var flags = _this.try_parse_int() | FLAG_NOVAR; var arity = _this.try_parse_int(); assert(tl_type.arity == arity); var tl_tree_type = new TlTreeType(flags, tl_type); // the arity unused for (var i = 0; i < arity; i++) { var child = _this.read_expr(tl_combinator); tl_tree_type.children.push(child); if (!(child.flags & FLAG_NOVAR)) { tl_tree_type.flags &= ~FLAG_NOVAR; } } return tl_tree_type; }; _this.read_array = function (tl_combinator) { var flags = FLAG_NOVAR; var multiplicity = _this.read_nat_expr(tl_combinator); var tl_tree_array = new TlTreeArray(flags, multiplicity, _this.read_args_list(tl_combinator)); for (var i = 0; i < tl_tree_array.args.length; i++) { if (!(tl_tree_array.args[i].flags & FLAG_NOVAR)) { tl_tree_array.flags &= ~FLAG_NOVAR; } } return tl_tree_array; }; _this.try_parse = function (res) { if (_this.p.get_error()) { throw Error("Wrong TL-scheme specified: " + _this.p.get_error() + " at " + _this.p.get_error_pos()); } return res; }; _this.try_parse_int = function () { return _this.try_parse(_this.p.fetch_int()); }; _this.try_parse_long = function () { return _this.try_parse(_this.p.fetch_long()); }; _this.try_parse_string = function () { return _this.try_parse(_this.p.fetch_string()); }; _this.p = new TlSimpleParser(data); _this.schema_version = -1; _this.config = new TlConfig(); return _this; } return TlConfigParser; }(TlBase); var read_tl_config = function (data) { if (!data) { throw Error('Config data is empty'); } if (data.length % 4 /* SIZE_OF_INT32 */ != 0) { throw Error("Config size = " + data.length + " is not multiple of " + 4 /* SIZE_OF_INT32 */ ); } var parser = new TlConfigParser(data); return parser.parse_config(); }; var read_tl_config_from_file = function (file_name, callback) { fs.readFile(file_name, function (err, data) { if (err) throw err; callback(read_tl_config(data)); }); }; export { read_tl_config, read_tl_config_from_file };