From 94873e595c6f231202929501570088849f3b8803 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Harrtell?= Date: Thu, 17 Sep 2020 21:21:14 +0200 Subject: [PATCH] [JS/TS] Modernize TypeScript / JavaScript flatbuffers support (#6095) --- .eslintrc.js | 13 + .gitignore | 5 + appveyor.yml | 2 + js/README.md | 1 + js/flatbuffers.js | 1398 ----------------- mjs/README.md | 1 + package.json | 23 +- tests/TypeScriptTest.sh | 1 + .../languages/Dockerfile.testing.node.10_13_0 | 2 + .../languages/Dockerfile.testing.node.11_2_0 | 2 + ts/builder.ts | 628 ++++++++ ts/byte-buffer.ts | 351 +++++ ts/constants.ts | 4 + ts/encoding.ts | 4 + ts/flatbuffers.ts | 33 + ts/long.ts | 23 + ts/types.ts | 14 + ts/utils.ts | 4 + tsconfig.json | 16 + tsconfig.mjs.json | 16 + yarn.lock | 956 +++++++++++ 21 files changed, 2093 insertions(+), 1404 deletions(-) create mode 100644 .eslintrc.js create mode 100644 js/README.md delete mode 100644 js/flatbuffers.js create mode 100644 mjs/README.md create mode 100644 ts/builder.ts create mode 100644 ts/byte-buffer.ts create mode 100644 ts/constants.ts create mode 100644 ts/encoding.ts create mode 100644 ts/flatbuffers.ts create mode 100644 ts/long.ts create mode 100644 ts/types.ts create mode 100644 ts/utils.ts create mode 100644 tsconfig.json create mode 100644 tsconfig.mjs.json create mode 100644 yarn.lock diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 00000000000..321169b07c0 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,13 @@ +/* eslint-env node */ + +module.exports = { + root: true, + parser: '@typescript-eslint/parser', + plugins: [ + '@typescript-eslint', + ], + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + ] +}; \ No newline at end of file diff --git a/.gitignore b/.gitignore index ab99dfa58e4..03fd44c7188 100644 --- a/.gitignore +++ b/.gitignore @@ -130,3 +130,8 @@ package-lock.json /*.ilk /*.pdb .clwb +js/*.js +js/*.d.ts +mjs/*.js +mjs/*.d.ts +yarn-error.log \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml index 6655f3cdde0..9806fe4bd6a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -86,6 +86,8 @@ test_script: - rem "---------------- JS -----------------" - "node --version" - "..\\%CONFIGURATION%\\flatc -b -I include_test monster_test.fbs unicode_test.json" + - "npm install" + - "npm run pretest" - "node JavaScriptTest ./monster_test_generated" - rem "-------------- Python ---------------" - where python diff --git a/js/README.md b/js/README.md new file mode 100644 index 00000000000..cbcebe051cd --- /dev/null +++ b/js/README.md @@ -0,0 +1 @@ +This folder is intentionally empty and will contain transpiled js modules in Common JS format after compiling with tsc. \ No newline at end of file diff --git a/js/flatbuffers.js b/js/flatbuffers.js deleted file mode 100644 index b1687b75c29..00000000000 --- a/js/flatbuffers.js +++ /dev/null @@ -1,1398 +0,0 @@ -/// @file -/// @addtogroup flatbuffers_javascript_api -/// @{ -/// @cond FLATBUFFERS_INTERNAL - -/** - * @fileoverview - * - * Need to suppress 'global this' error so the Node.js export line doesn't cause - * closure compile to error out. - * @suppress {globalThis} - */ - -/** - * @const - * @namespace - */ -var flatbuffers = {}; - -/** - * @typedef {number} - */ -flatbuffers.Offset; - -/** - * @typedef {{ - * bb: flatbuffers.ByteBuffer, - * bb_pos: number - * }} - */ -flatbuffers.Table; - -/** - * @type {number} - * @const - */ -flatbuffers.SIZEOF_SHORT = 2; - -/** - * @type {number} - * @const - */ -flatbuffers.SIZEOF_INT = 4; - -/** - * @type {number} - * @const - */ -flatbuffers.FILE_IDENTIFIER_LENGTH = 4; - -/** - * @type {number} - * @const - */ -flatbuffers.SIZE_PREFIX_LENGTH = 4; - -/** - * @param {number} low - * @param {number} high - * @returns {flatbuffers.Long} - */ -flatbuffers.createLong = function(low, high) { - return flatbuffers.Long.create(low, high); -}; - -/** - * @enum {number} - */ -flatbuffers.Encoding = { - UTF8_BYTES: 1, - UTF16_STRING: 2 -}; - -/** - * @type {Int32Array} - * @const - */ -flatbuffers.int32 = new Int32Array(2); - -/** - * @type {Float32Array} - * @const - */ -flatbuffers.float32 = new Float32Array(flatbuffers.int32.buffer); - -/** - * @type {Float64Array} - * @const - */ -flatbuffers.float64 = new Float64Array(flatbuffers.int32.buffer); - -/** - * @type {boolean} - * @const - */ -flatbuffers.isLittleEndian = new Uint16Array(new Uint8Array([1, 0]).buffer)[0] === 1; - -//////////////////////////////////////////////////////////////////////////////// - -/** - * @constructor - * @param {number} low - * @param {number} high - */ -flatbuffers.Long = function(low, high) { - /** - * @type {number} - * @const - */ - this.low = low | 0; - - /** - * @type {number} - * @const - */ - this.high = high | 0; -}; - -/** - * @param {number} low - * @param {number} high - * @returns {!flatbuffers.Long} - */ -flatbuffers.Long.create = function(low, high) { - // Special-case zero to avoid GC overhead for default values - return low == 0 && high == 0 ? flatbuffers.Long.ZERO : new flatbuffers.Long(low, high); -}; - -/** - * @returns {number} - */ -flatbuffers.Long.prototype.toFloat64 = function() { - return (this.low >>> 0) + this.high * 0x100000000; -}; - -/** - * @param {flatbuffers.Long} other - * @returns {boolean} - */ -flatbuffers.Long.prototype.equals = function(other) { - return this.low == other.low && this.high == other.high; -}; - -/** - * @type {!flatbuffers.Long} - * @const - */ -flatbuffers.Long.ZERO = new flatbuffers.Long(0, 0); - -/// @endcond -//////////////////////////////////////////////////////////////////////////////// -/** - * Create a FlatBufferBuilder. - * - * @constructor - * @param {number=} opt_initial_size - */ -flatbuffers.Builder = function(opt_initial_size) { - if (!opt_initial_size) { - var initial_size = 1024; - } else { - var initial_size = opt_initial_size; - } - - /** - * @type {flatbuffers.ByteBuffer} - * @private - */ - this.bb = flatbuffers.ByteBuffer.allocate(initial_size); - - /** - * Remaining space in the ByteBuffer. - * - * @type {number} - * @private - */ - this.space = initial_size; - - /** - * Minimum alignment encountered so far. - * - * @type {number} - * @private - */ - this.minalign = 1; - - /** - * The vtable for the current table. - * - * @type {Array.} - * @private - */ - this.vtable = null; - - /** - * The amount of fields we're actually using. - * - * @type {number} - * @private - */ - this.vtable_in_use = 0; - - /** - * Whether we are currently serializing a table. - * - * @type {boolean} - * @private - */ - this.isNested = false; - - /** - * Starting offset of the current struct/table. - * - * @type {number} - * @private - */ - this.object_start = 0; - - /** - * List of offsets of all vtables. - * - * @type {Array.} - * @private - */ - this.vtables = []; - - /** - * For the current vector being built. - * - * @type {number} - * @private - */ - this.vector_num_elems = 0; - - /** - * False omits default values from the serialized data - * - * @type {boolean} - * @private - */ - this.force_defaults = false; -}; - -flatbuffers.Builder.prototype.clear = function() { - this.bb.clear(); - this.space = this.bb.capacity(); - this.minalign = 1; - this.vtable = null; - this.vtable_in_use = 0; - this.isNested = false; - this.object_start = 0; - this.vtables = []; - this.vector_num_elems = 0; - this.force_defaults = false; - this.string_maps = null; -}; - -/** - * In order to save space, fields that are set to their default value - * don't get serialized into the buffer. Forcing defaults provides a - * way to manually disable this optimization. - * - * @param {boolean} forceDefaults true always serializes default values - */ -flatbuffers.Builder.prototype.forceDefaults = function(forceDefaults) { - this.force_defaults = forceDefaults; -}; - -/** - * Get the ByteBuffer representing the FlatBuffer. Only call this after you've - * called finish(). The actual data starts at the ByteBuffer's current position, - * not necessarily at 0. - * - * @returns {flatbuffers.ByteBuffer} - */ -flatbuffers.Builder.prototype.dataBuffer = function() { - return this.bb; -}; - -/** - * Get the bytes representing the FlatBuffer. Only call this after you've - * called finish(). - * - * @returns {!Uint8Array} - */ -flatbuffers.Builder.prototype.asUint8Array = function() { - return this.bb.bytes().subarray(this.bb.position(), this.bb.position() + this.offset()); -}; - -/// @cond FLATBUFFERS_INTERNAL -/** - * Prepare to write an element of `size` after `additional_bytes` have been - * written, e.g. if you write a string, you need to align such the int length - * field is aligned to 4 bytes, and the string data follows it directly. If all - * you need to do is alignment, `additional_bytes` will be 0. - * - * @param {number} size This is the of the new element to write - * @param {number} additional_bytes The padding size - */ -flatbuffers.Builder.prototype.prep = function(size, additional_bytes) { - // Track the biggest thing we've ever aligned to. - if (size > this.minalign) { - this.minalign = size; - } - - // Find the amount of alignment needed such that `size` is properly - // aligned after `additional_bytes` - var align_size = ((~(this.bb.capacity() - this.space + additional_bytes)) + 1) & (size - 1); - - // Reallocate the buffer if needed. - while (this.space < align_size + size + additional_bytes) { - var old_buf_size = this.bb.capacity(); - this.bb = flatbuffers.Builder.growByteBuffer(this.bb); - this.space += this.bb.capacity() - old_buf_size; - } - - this.pad(align_size); -}; - -/** - * @param {number} byte_size - */ -flatbuffers.Builder.prototype.pad = function(byte_size) { - for (var i = 0; i < byte_size; i++) { - this.bb.writeInt8(--this.space, 0); - } -}; - -/** - * @param {number} value - */ -flatbuffers.Builder.prototype.writeInt8 = function(value) { - this.bb.writeInt8(this.space -= 1, value); -}; - -/** - * @param {number} value - */ -flatbuffers.Builder.prototype.writeInt16 = function(value) { - this.bb.writeInt16(this.space -= 2, value); -}; - -/** - * @param {number} value - */ -flatbuffers.Builder.prototype.writeInt32 = function(value) { - this.bb.writeInt32(this.space -= 4, value); -}; - -/** - * @param {flatbuffers.Long} value - */ -flatbuffers.Builder.prototype.writeInt64 = function(value) { - this.bb.writeInt64(this.space -= 8, value); -}; - -/** - * @param {number} value - */ -flatbuffers.Builder.prototype.writeFloat32 = function(value) { - this.bb.writeFloat32(this.space -= 4, value); -}; - -/** - * @param {number} value - */ -flatbuffers.Builder.prototype.writeFloat64 = function(value) { - this.bb.writeFloat64(this.space -= 8, value); -}; -/// @endcond - -/** - * Add an `int8` to the buffer, properly aligned, and grows the buffer (if necessary). - * @param {number} value The `int8` to add the the buffer. - */ -flatbuffers.Builder.prototype.addInt8 = function(value) { - this.prep(1, 0); - this.writeInt8(value); -}; - -/** - * Add an `int16` to the buffer, properly aligned, and grows the buffer (if necessary). - * @param {number} value The `int16` to add the the buffer. - */ -flatbuffers.Builder.prototype.addInt16 = function(value) { - this.prep(2, 0); - this.writeInt16(value); -}; - -/** - * Add an `int32` to the buffer, properly aligned, and grows the buffer (if necessary). - * @param {number} value The `int32` to add the the buffer. - */ -flatbuffers.Builder.prototype.addInt32 = function(value) { - this.prep(4, 0); - this.writeInt32(value); -}; - -/** - * Add an `int64` to the buffer, properly aligned, and grows the buffer (if necessary). - * @param {flatbuffers.Long} value The `int64` to add the the buffer. - */ -flatbuffers.Builder.prototype.addInt64 = function(value) { - this.prep(8, 0); - this.writeInt64(value); -}; - -/** - * Add a `float32` to the buffer, properly aligned, and grows the buffer (if necessary). - * @param {number} value The `float32` to add the the buffer. - */ -flatbuffers.Builder.prototype.addFloat32 = function(value) { - this.prep(4, 0); - this.writeFloat32(value); -}; - -/** - * Add a `float64` to the buffer, properly aligned, and grows the buffer (if necessary). - * @param {number} value The `float64` to add the the buffer. - */ -flatbuffers.Builder.prototype.addFloat64 = function(value) { - this.prep(8, 0); - this.writeFloat64(value); -}; - -/// @cond FLATBUFFERS_INTERNAL -/** - * @param {number} voffset - * @param {number} value - * @param {number} defaultValue - */ -flatbuffers.Builder.prototype.addFieldInt8 = function(voffset, value, defaultValue) { - if (this.force_defaults || value != defaultValue) { - this.addInt8(value); - this.slot(voffset); - } -}; - -/** - * @param {number} voffset - * @param {number} value - * @param {number} defaultValue - */ -flatbuffers.Builder.prototype.addFieldInt16 = function(voffset, value, defaultValue) { - if (this.force_defaults || value != defaultValue) { - this.addInt16(value); - this.slot(voffset); - } -}; - -/** - * @param {number} voffset - * @param {number} value - * @param {number} defaultValue - */ -flatbuffers.Builder.prototype.addFieldInt32 = function(voffset, value, defaultValue) { - if (this.force_defaults || value != defaultValue) { - this.addInt32(value); - this.slot(voffset); - } -}; - -/** - * @param {number} voffset - * @param {flatbuffers.Long} value - * @param {flatbuffers.Long} defaultValue - */ -flatbuffers.Builder.prototype.addFieldInt64 = function(voffset, value, defaultValue) { - if (this.force_defaults || !value.equals(defaultValue)) { - this.addInt64(value); - this.slot(voffset); - } -}; - -/** - * @param {number} voffset - * @param {number} value - * @param {number} defaultValue - */ -flatbuffers.Builder.prototype.addFieldFloat32 = function(voffset, value, defaultValue) { - if (this.force_defaults || value != defaultValue) { - this.addFloat32(value); - this.slot(voffset); - } -}; - -/** - * @param {number} voffset - * @param {number} value - * @param {number} defaultValue - */ -flatbuffers.Builder.prototype.addFieldFloat64 = function(voffset, value, defaultValue) { - if (this.force_defaults || value != defaultValue) { - this.addFloat64(value); - this.slot(voffset); - } -}; - -/** - * @param {number} voffset - * @param {flatbuffers.Offset} value - * @param {flatbuffers.Offset} defaultValue - */ -flatbuffers.Builder.prototype.addFieldOffset = function(voffset, value, defaultValue) { - if (this.force_defaults || value != defaultValue) { - this.addOffset(value); - this.slot(voffset); - } -}; - -/** - * Structs are stored inline, so nothing additional is being added. `d` is always 0. - * - * @param {number} voffset - * @param {flatbuffers.Offset} value - * @param {flatbuffers.Offset} defaultValue - */ -flatbuffers.Builder.prototype.addFieldStruct = function(voffset, value, defaultValue) { - if (value != defaultValue) { - this.nested(value); - this.slot(voffset); - } -}; - -/** - * Structures are always stored inline, they need to be created right - * where they're used. You'll get this assertion failure if you - * created it elsewhere. - * - * @param {flatbuffers.Offset} obj The offset of the created object - */ -flatbuffers.Builder.prototype.nested = function(obj) { - if (obj != this.offset()) { - throw new Error('FlatBuffers: struct must be serialized inline.'); - } -}; - -/** - * Should not be creating any other object, string or vector - * while an object is being constructed - */ -flatbuffers.Builder.prototype.notNested = function() { - if (this.isNested) { - throw new Error('FlatBuffers: object serialization must not be nested.'); - } -}; - -/** - * Set the current vtable at `voffset` to the current location in the buffer. - * - * @param {number} voffset - */ -flatbuffers.Builder.prototype.slot = function(voffset) { - this.vtable[voffset] = this.offset(); -}; - -/** - * @returns {flatbuffers.Offset} Offset relative to the end of the buffer. - */ -flatbuffers.Builder.prototype.offset = function() { - return this.bb.capacity() - this.space; -}; - -/** - * Doubles the size of the backing ByteBuffer and copies the old data towards - * the end of the new buffer (since we build the buffer backwards). - * - * @param {flatbuffers.ByteBuffer} bb The current buffer with the existing data - * @returns {!flatbuffers.ByteBuffer} A new byte buffer with the old data copied - * to it. The data is located at the end of the buffer. - * - * uint8Array.set() formally takes {Array|ArrayBufferView}, so to pass - * it a uint8Array we need to suppress the type check: - * @suppress {checkTypes} - */ -flatbuffers.Builder.growByteBuffer = function(bb) { - var old_buf_size = bb.capacity(); - - // Ensure we don't grow beyond what fits in an int. - if (old_buf_size & 0xC0000000) { - throw new Error('FlatBuffers: cannot grow buffer beyond 2 gigabytes.'); - } - - var new_buf_size = old_buf_size << 1; - var nbb = flatbuffers.ByteBuffer.allocate(new_buf_size); - nbb.setPosition(new_buf_size - old_buf_size); - nbb.bytes().set(bb.bytes(), new_buf_size - old_buf_size); - return nbb; -}; -/// @endcond - -/** - * Adds on offset, relative to where it will be written. - * - * @param {flatbuffers.Offset} offset The offset to add. - */ -flatbuffers.Builder.prototype.addOffset = function(offset) { - this.prep(flatbuffers.SIZEOF_INT, 0); // Ensure alignment is already done. - this.writeInt32(this.offset() - offset + flatbuffers.SIZEOF_INT); -}; - -/// @cond FLATBUFFERS_INTERNAL -/** - * Start encoding a new object in the buffer. Users will not usually need to - * call this directly. The FlatBuffers compiler will generate helper methods - * that call this method internally. - * - * @param {number} numfields - */ -flatbuffers.Builder.prototype.startObject = function(numfields) { - this.notNested(); - if (this.vtable == null) { - this.vtable = []; - } - this.vtable_in_use = numfields; - for (var i = 0; i < numfields; i++) { - this.vtable[i] = 0; // This will push additional elements as needed - } - this.isNested = true; - this.object_start = this.offset(); -}; - -/** - * Finish off writing the object that is under construction. - * - * @returns {flatbuffers.Offset} The offset to the object inside `dataBuffer` - */ -flatbuffers.Builder.prototype.endObject = function() { - if (this.vtable == null || !this.isNested) { - throw new Error('FlatBuffers: endObject called without startObject'); - } - - this.addInt32(0); - var vtableloc = this.offset(); - - // Trim trailing zeroes. - var i = this.vtable_in_use - 1; - for (; i >= 0 && this.vtable[i] == 0; i--) {} - var trimmed_size = i + 1; - - // Write out the current vtable. - for (; i >= 0; i--) { - // Offset relative to the start of the table. - this.addInt16(this.vtable[i] != 0 ? vtableloc - this.vtable[i] : 0); - } - - var standard_fields = 2; // The fields below: - this.addInt16(vtableloc - this.object_start); - var len = (trimmed_size + standard_fields) * flatbuffers.SIZEOF_SHORT; - this.addInt16(len); - - // Search for an existing vtable that matches the current one. - var existing_vtable = 0; - var vt1 = this.space; -outer_loop: - for (i = 0; i < this.vtables.length; i++) { - var vt2 = this.bb.capacity() - this.vtables[i]; - if (len == this.bb.readInt16(vt2)) { - for (var j = flatbuffers.SIZEOF_SHORT; j < len; j += flatbuffers.SIZEOF_SHORT) { - if (this.bb.readInt16(vt1 + j) != this.bb.readInt16(vt2 + j)) { - continue outer_loop; - } - } - existing_vtable = this.vtables[i]; - break; - } - } - - if (existing_vtable) { - // Found a match: - // Remove the current vtable. - this.space = this.bb.capacity() - vtableloc; - - // Point table to existing vtable. - this.bb.writeInt32(this.space, existing_vtable - vtableloc); - } else { - // No match: - // Add the location of the current vtable to the list of vtables. - this.vtables.push(this.offset()); - - // Point table to current vtable. - this.bb.writeInt32(this.bb.capacity() - vtableloc, this.offset() - vtableloc); - } - - this.isNested = false; - return vtableloc; -}; -/// @endcond - -/** - * Finalize a buffer, poiting to the given `root_table`. - * - * @param {flatbuffers.Offset} root_table - * @param {string=} opt_file_identifier - * @param {boolean=} opt_size_prefix - */ -flatbuffers.Builder.prototype.finish = function(root_table, opt_file_identifier, opt_size_prefix) { - var size_prefix = opt_size_prefix ? flatbuffers.SIZE_PREFIX_LENGTH : 0; - if (opt_file_identifier) { - var file_identifier = opt_file_identifier; - this.prep(this.minalign, flatbuffers.SIZEOF_INT + - flatbuffers.FILE_IDENTIFIER_LENGTH + size_prefix); - if (file_identifier.length != flatbuffers.FILE_IDENTIFIER_LENGTH) { - throw new Error('FlatBuffers: file identifier must be length ' + - flatbuffers.FILE_IDENTIFIER_LENGTH); - } - for (var i = flatbuffers.FILE_IDENTIFIER_LENGTH - 1; i >= 0; i--) { - this.writeInt8(file_identifier.charCodeAt(i)); - } - } - this.prep(this.minalign, flatbuffers.SIZEOF_INT + size_prefix); - this.addOffset(root_table); - if (size_prefix) { - this.addInt32(this.bb.capacity() - this.space); - } - this.bb.setPosition(this.space); -}; - -/** - * Finalize a size prefixed buffer, pointing to the given `root_table`. - * - * @param {flatbuffers.Offset} root_table - * @param {string=} opt_file_identifier - */ -flatbuffers.Builder.prototype.finishSizePrefixed = function (root_table, opt_file_identifier) { - this.finish(root_table, opt_file_identifier, true); -}; - -/// @cond FLATBUFFERS_INTERNAL -/** - * This checks a required field has been set in a given table that has - * just been constructed. - * - * @param {flatbuffers.Offset} table - * @param {number} field - */ -flatbuffers.Builder.prototype.requiredField = function(table, field) { - var table_start = this.bb.capacity() - table; - var vtable_start = table_start - this.bb.readInt32(table_start); - var ok = this.bb.readInt16(vtable_start + field) != 0; - - // If this fails, the caller will show what field needs to be set. - if (!ok) { - throw new Error('FlatBuffers: field ' + field + ' must be set'); - } -}; - -/** - * Start a new array/vector of objects. Users usually will not call - * this directly. The FlatBuffers compiler will create a start/end - * method for vector types in generated code. - * - * @param {number} elem_size The size of each element in the array - * @param {number} num_elems The number of elements in the array - * @param {number} alignment The alignment of the array - */ -flatbuffers.Builder.prototype.startVector = function(elem_size, num_elems, alignment) { - this.notNested(); - this.vector_num_elems = num_elems; - this.prep(flatbuffers.SIZEOF_INT, elem_size * num_elems); - this.prep(alignment, elem_size * num_elems); // Just in case alignment > int. -}; - -/** - * Finish off the creation of an array and all its elements. The array must be - * created with `startVector`. - * - * @returns {flatbuffers.Offset} The offset at which the newly created array - * starts. - */ -flatbuffers.Builder.prototype.endVector = function() { - this.writeInt32(this.vector_num_elems); - return this.offset(); -}; -/// @endcond - -/** - * Encode the string `s` in the buffer using UTF-8. If the string passed has - * already been seen, we return the offset of the already written string - * - * @param {string|Uint8Array} s The string to encode - * @return {flatbuffers.Offset} The offset in the buffer where the encoded string starts - */ -flatbuffers.Builder.prototype.createSharedString = function(s) { - if (!s) { return 0 } - - if (!this.string_maps) { - this.string_maps = new Map(); - } - - if (this.string_maps.has(s)) { - return this.string_maps.get(s) - } - let offset = this.createString(s) - this.string_maps.set(s, offset) - return offset -} - -/** - * Encode the string `s` in the buffer using UTF-8. If a Uint8Array is passed - * instead of a string, it is assumed to contain valid UTF-8 encoded data. - * - * @param {string|Uint8Array} s The string to encode - * @return {flatbuffers.Offset} The offset in the buffer where the encoded string starts - */ -flatbuffers.Builder.prototype.createString = function(s) { - if (!s) { return 0 } - if (s instanceof Uint8Array) { - var utf8 = s; - } else { - var utf8 = []; - var i = 0; - - while (i < s.length) { - var codePoint; - - // Decode UTF-16 - var a = s.charCodeAt(i++); - if (a < 0xD800 || a >= 0xDC00) { - codePoint = a; - } else { - var b = s.charCodeAt(i++); - codePoint = (a << 10) + b + (0x10000 - (0xD800 << 10) - 0xDC00); - } - - // Encode UTF-8 - if (codePoint < 0x80) { - utf8.push(codePoint); - } else { - if (codePoint < 0x800) { - utf8.push(((codePoint >> 6) & 0x1F) | 0xC0); - } else { - if (codePoint < 0x10000) { - utf8.push(((codePoint >> 12) & 0x0F) | 0xE0); - } else { - utf8.push( - ((codePoint >> 18) & 0x07) | 0xF0, - ((codePoint >> 12) & 0x3F) | 0x80); - } - utf8.push(((codePoint >> 6) & 0x3F) | 0x80); - } - utf8.push((codePoint & 0x3F) | 0x80); - } - } - } - - this.addInt8(0); - this.startVector(1, utf8.length, 1); - this.bb.setPosition(this.space -= utf8.length); - for (var i = 0, offset = this.space, bytes = this.bb.bytes(); i < utf8.length; i++) { - bytes[offset++] = utf8[i]; - } - return this.endVector(); -}; - -/** - * A helper function to avoid generated code depending on this file directly. - * - * @param {number} low - * @param {number} high - * @returns {!flatbuffers.Long} - */ -flatbuffers.Builder.prototype.createLong = function(low, high) { - return flatbuffers.Long.create(low, high); -}; - -/** - * A helper function to pack an object - * - * @returns offset of obj - */ -flatbuffers.Builder.prototype.createObjectOffset = function(obj) { - if(obj === null) { - return 0 - } - - if(typeof obj === 'string') { - return this.createString(obj); - } else { - return obj.pack(this); - } -} - -/** - * A helper function to pack a list of object - * - * @returns list of offsets of each non null object - */ -flatbuffers.Builder.prototype.createObjectOffsetList = function(list) { - let ret = []; - - for(let i = 0; i < list.length; ++i) { - let val = list[i]; - - if(val !== null) { - ret.push(this.createObjectOffset(val)); - } else { - throw new Error( - 'FlatBuffers: Argument for createObjectOffsetList cannot contain null.'); - } - } - - return ret; -}; - -flatbuffers.Builder.prototype.createStructOffsetList = function(list, startFunc) { - startFunc(this, list.length); - this.createObjectOffsetList(list); - return this.endVector(); -} - -//////////////////////////////////////////////////////////////////////////////// -/// @cond FLATBUFFERS_INTERNAL -/** - * Create a new ByteBuffer with a given array of bytes (`Uint8Array`). - * - * @constructor - * @param {Uint8Array} bytes - */ -flatbuffers.ByteBuffer = function(bytes) { - /** - * @type {Uint8Array} - * @private - */ - this.bytes_ = bytes; - - /** - * @type {number} - * @private - */ - this.position_ = 0; -}; - -/** - * Create and allocate a new ByteBuffer with a given size. - * - * @param {number} byte_size - * @returns {!flatbuffers.ByteBuffer} - */ -flatbuffers.ByteBuffer.allocate = function(byte_size) { - return new flatbuffers.ByteBuffer(new Uint8Array(byte_size)); -}; - -flatbuffers.ByteBuffer.prototype.clear = function() { - this.position_ = 0; -}; - -/** - * Get the underlying `Uint8Array`. - * - * @returns {Uint8Array} - */ -flatbuffers.ByteBuffer.prototype.bytes = function() { - return this.bytes_; -}; - -/** - * Get the buffer's position. - * - * @returns {number} - */ -flatbuffers.ByteBuffer.prototype.position = function() { - return this.position_; -}; - -/** - * Set the buffer's position. - * - * @param {number} position - */ -flatbuffers.ByteBuffer.prototype.setPosition = function(position) { - this.position_ = position; -}; - -/** - * Get the buffer's capacity. - * - * @returns {number} - */ -flatbuffers.ByteBuffer.prototype.capacity = function() { - return this.bytes_.length; -}; - -/** - * @param {number} offset - * @returns {number} - */ -flatbuffers.ByteBuffer.prototype.readInt8 = function(offset) { - return this.readUint8(offset) << 24 >> 24; -}; - -/** - * @param {number} offset - * @returns {number} - */ -flatbuffers.ByteBuffer.prototype.readUint8 = function(offset) { - return this.bytes_[offset]; -}; - -/** - * @param {number} offset - * @returns {number} - */ -flatbuffers.ByteBuffer.prototype.readInt16 = function(offset) { - return this.readUint16(offset) << 16 >> 16; -}; - -/** - * @param {number} offset - * @returns {number} - */ -flatbuffers.ByteBuffer.prototype.readUint16 = function(offset) { - return this.bytes_[offset] | this.bytes_[offset + 1] << 8; -}; - -/** - * @param {number} offset - * @returns {number} - */ -flatbuffers.ByteBuffer.prototype.readInt32 = function(offset) { - return this.bytes_[offset] | this.bytes_[offset + 1] << 8 | this.bytes_[offset + 2] << 16 | this.bytes_[offset + 3] << 24; -}; - -/** - * @param {number} offset - * @returns {number} - */ -flatbuffers.ByteBuffer.prototype.readUint32 = function(offset) { - return this.readInt32(offset) >>> 0; -}; - -/** - * @param {number} offset - * @returns {!flatbuffers.Long} - */ -flatbuffers.ByteBuffer.prototype.readInt64 = function(offset) { - return new flatbuffers.Long(this.readInt32(offset), this.readInt32(offset + 4)); -}; - -/** - * @param {number} offset - * @returns {!flatbuffers.Long} - */ -flatbuffers.ByteBuffer.prototype.readUint64 = function(offset) { - return new flatbuffers.Long(this.readUint32(offset), this.readUint32(offset + 4)); -}; - -/** - * @param {number} offset - * @returns {number} - */ -flatbuffers.ByteBuffer.prototype.readFloat32 = function(offset) { - flatbuffers.int32[0] = this.readInt32(offset); - return flatbuffers.float32[0]; -}; - -/** - * @param {number} offset - * @returns {number} - */ -flatbuffers.ByteBuffer.prototype.readFloat64 = function(offset) { - flatbuffers.int32[flatbuffers.isLittleEndian ? 0 : 1] = this.readInt32(offset); - flatbuffers.int32[flatbuffers.isLittleEndian ? 1 : 0] = this.readInt32(offset + 4); - return flatbuffers.float64[0]; -}; - -/** - * @param {number} offset - * @param {number|boolean} value - */ -flatbuffers.ByteBuffer.prototype.writeInt8 = function(offset, value) { - this.bytes_[offset] = /** @type {number} */(value); -}; - -/** - * @param {number} offset - * @param {number} value - */ -flatbuffers.ByteBuffer.prototype.writeUint8 = function(offset, value) { - this.bytes_[offset] = value; -}; - -/** - * @param {number} offset - * @param {number} value - */ -flatbuffers.ByteBuffer.prototype.writeInt16 = function(offset, value) { - this.bytes_[offset] = value; - this.bytes_[offset + 1] = value >> 8; -}; - -/** - * @param {number} offset - * @param {number} value - */ -flatbuffers.ByteBuffer.prototype.writeUint16 = function(offset, value) { - this.bytes_[offset] = value; - this.bytes_[offset + 1] = value >> 8; -}; - -/** - * @param {number} offset - * @param {number} value - */ -flatbuffers.ByteBuffer.prototype.writeInt32 = function(offset, value) { - this.bytes_[offset] = value; - this.bytes_[offset + 1] = value >> 8; - this.bytes_[offset + 2] = value >> 16; - this.bytes_[offset + 3] = value >> 24; -}; - -/** - * @param {number} offset - * @param {number} value - */ -flatbuffers.ByteBuffer.prototype.writeUint32 = function(offset, value) { - this.bytes_[offset] = value; - this.bytes_[offset + 1] = value >> 8; - this.bytes_[offset + 2] = value >> 16; - this.bytes_[offset + 3] = value >> 24; -}; - -/** - * @param {number} offset - * @param {flatbuffers.Long} value - */ -flatbuffers.ByteBuffer.prototype.writeInt64 = function(offset, value) { - this.writeInt32(offset, value.low); - this.writeInt32(offset + 4, value.high); -}; - -/** - * @param {number} offset - * @param {flatbuffers.Long} value - */ -flatbuffers.ByteBuffer.prototype.writeUint64 = function(offset, value) { - this.writeUint32(offset, value.low); - this.writeUint32(offset + 4, value.high); -}; - -/** - * @param {number} offset - * @param {number} value - */ -flatbuffers.ByteBuffer.prototype.writeFloat32 = function(offset, value) { - flatbuffers.float32[0] = value; - this.writeInt32(offset, flatbuffers.int32[0]); -}; - -/** - * @param {number} offset - * @param {number} value - */ -flatbuffers.ByteBuffer.prototype.writeFloat64 = function(offset, value) { - flatbuffers.float64[0] = value; - this.writeInt32(offset, flatbuffers.int32[flatbuffers.isLittleEndian ? 0 : 1]); - this.writeInt32(offset + 4, flatbuffers.int32[flatbuffers.isLittleEndian ? 1 : 0]); -}; - -/** - * Return the file identifier. Behavior is undefined for FlatBuffers whose - * schema does not include a file_identifier (likely points at padding or the - * start of a the root vtable). - * @returns {string} - */ -flatbuffers.ByteBuffer.prototype.getBufferIdentifier = function() { - if (this.bytes_.length < this.position_ + flatbuffers.SIZEOF_INT + - flatbuffers.FILE_IDENTIFIER_LENGTH) { - throw new Error( - 'FlatBuffers: ByteBuffer is too short to contain an identifier.'); - } - var result = ""; - for (var i = 0; i < flatbuffers.FILE_IDENTIFIER_LENGTH; i++) { - result += String.fromCharCode( - this.readInt8(this.position_ + flatbuffers.SIZEOF_INT + i)); - } - return result; -}; - -/** - * Look up a field in the vtable, return an offset into the object, or 0 if the - * field is not present. - * - * @param {number} bb_pos - * @param {number} vtable_offset - * @returns {number} - */ -flatbuffers.ByteBuffer.prototype.__offset = function(bb_pos, vtable_offset) { - var vtable = bb_pos - this.readInt32(bb_pos); - return vtable_offset < this.readInt16(vtable) ? this.readInt16(vtable + vtable_offset) : 0; -}; - -/** - * Initialize any Table-derived type to point to the union at the given offset. - * - * @param {flatbuffers.Table} t - * @param {number} offset - * @returns {flatbuffers.Table} - */ -flatbuffers.ByteBuffer.prototype.__union = function(t, offset) { - t.bb_pos = offset + this.readInt32(offset); - t.bb = this; - return t; -}; - -/** - * Create a JavaScript string from UTF-8 data stored inside the FlatBuffer. - * This allocates a new string and converts to wide chars upon each access. - * - * To avoid the conversion to UTF-16, pass flatbuffers.Encoding.UTF8_BYTES as - * the "optionalEncoding" argument. This is useful for avoiding conversion to - * and from UTF-16 when the data will just be packaged back up in another - * FlatBuffer later on. - * - * @param {number} offset - * @param {flatbuffers.Encoding=} opt_encoding Defaults to UTF16_STRING - * @returns {string|!Uint8Array} - */ -flatbuffers.ByteBuffer.prototype.__string = function(offset, opt_encoding) { - offset += this.readInt32(offset); - - var length = this.readInt32(offset); - var result = ''; - var i = 0; - - offset += flatbuffers.SIZEOF_INT; - - if (opt_encoding === flatbuffers.Encoding.UTF8_BYTES) { - return this.bytes_.subarray(offset, offset + length); - } - - while (i < length) { - var codePoint; - - // Decode UTF-8 - var a = this.readUint8(offset + i++); - if (a < 0xC0) { - codePoint = a; - } else { - var b = this.readUint8(offset + i++); - if (a < 0xE0) { - codePoint = - ((a & 0x1F) << 6) | - (b & 0x3F); - } else { - var c = this.readUint8(offset + i++); - if (a < 0xF0) { - codePoint = - ((a & 0x0F) << 12) | - ((b & 0x3F) << 6) | - (c & 0x3F); - } else { - var d = this.readUint8(offset + i++); - codePoint = - ((a & 0x07) << 18) | - ((b & 0x3F) << 12) | - ((c & 0x3F) << 6) | - (d & 0x3F); - } - } - } - - // Encode UTF-16 - if (codePoint < 0x10000) { - result += String.fromCharCode(codePoint); - } else { - codePoint -= 0x10000; - result += String.fromCharCode( - (codePoint >> 10) + 0xD800, - (codePoint & ((1 << 10) - 1)) + 0xDC00); - } - } - - return result; -}; - -/** - * Handle unions that can contain string as its member, if a Table-derived type then initialize it, - * if a string then return a new one - * - * WARNING: strings are immutable in JS so we can't change the string that the user gave us, this - * makes the behaviour of __union_with_string different compared to __union - * - * @param {flatbuffers.Table|string} o - * @param {number} offset - * @returns {flatbuffers.Table|string} - */ -flatbuffers.ByteBuffer.prototype.__union_with_string = function(o, offset) { - if(typeof o === 'string') { - return this.__string(offset); - } - return this.__union(o, offset); -}; - -/** - * Retrieve the relative offset stored at "offset" - * @param {number} offset - * @returns {number} - */ -flatbuffers.ByteBuffer.prototype.__indirect = function(offset) { - return offset + this.readInt32(offset); -}; - -/** - * Get the start of data of a vector whose offset is stored at "offset" in this object. - * - * @param {number} offset - * @returns {number} - */ -flatbuffers.ByteBuffer.prototype.__vector = function(offset) { - return offset + this.readInt32(offset) + flatbuffers.SIZEOF_INT; // data starts after the length -}; - -/** - * Get the length of a vector whose offset is stored at "offset" in this object. - * - * @param {number} offset - * @returns {number} - */ -flatbuffers.ByteBuffer.prototype.__vector_len = function(offset) { - return this.readInt32(offset + this.readInt32(offset)); -}; - -/** - * @param {string} ident - * @returns {boolean} - */ -flatbuffers.ByteBuffer.prototype.__has_identifier = function(ident) { - if (ident.length != flatbuffers.FILE_IDENTIFIER_LENGTH) { - throw new Error('FlatBuffers: file identifier must be length ' + - flatbuffers.FILE_IDENTIFIER_LENGTH); - } - for (var i = 0; i < flatbuffers.FILE_IDENTIFIER_LENGTH; i++) { - if (ident.charCodeAt(i) != this.readInt8(this.position_ + flatbuffers.SIZEOF_INT + i)) { - return false; - } - } - return true; -}; - -/** - * A helper function to avoid generated code depending on this file directly. - * - * @param {number} low - * @param {number} high - * @returns {!flatbuffers.Long} - */ -flatbuffers.ByteBuffer.prototype.createLong = function(low, high) { - return flatbuffers.Long.create(low, high); -}; - -/** - * A helper function for generating list for obj api - * @param listAccessor function that accepts an index and return data at that index - * @param {number} listLength - * @returns {any[]} - */ -flatbuffers.ByteBuffer.prototype.createScalarList = function(listAccessor, listLength) { - let ret = []; - for(let i = 0; i < listLength; ++i) { - if(listAccessor(i) !== null) { - ret.push(listAccessor(i)); - } - } - - return ret; -}; - -/** - * This function is here only to get around typescript type system - */ -flatbuffers.ByteBuffer.prototype.createStringList = function(listAccessor, listLength) { - return this.createScalarList(listAccessor, listLength); -}; - -/** - * A helper function for generating list for obj api - * @param listAccessor function that accepts an index and return data at that index - * @param listLength {number} listLength - * @param res any[] result list - */ -flatbuffers.ByteBuffer.prototype.createObjList = function(listAccessor, listLength) { - let ret = []; - for(let i = 0; i < listLength; ++i) { - let val = listAccessor(i); - if(val !== null) { - ret.push(val.unpack()); - } - } - - return ret; -}; - -// Exports for Node.js and RequireJS -this.flatbuffers = flatbuffers; - -/// @endcond -/// @} diff --git a/mjs/README.md b/mjs/README.md new file mode 100644 index 00000000000..e3ca9db9d4c --- /dev/null +++ b/mjs/README.md @@ -0,0 +1 @@ +This folder is intentionally empty and will contain transpiled js modules in ES modules format after compiling with tsc. \ No newline at end of file diff --git a/package.json b/package.json index d01680a0f70..4b9f71f3042 100644 --- a/package.json +++ b/package.json @@ -3,19 +3,24 @@ "version": "1.12.0", "description": "Memory Efficient Serialization Library", "files": [ - "js/flatbuffers.js", - "js/flatbuffers.mjs" + "js/*.js", + "js/*.d.ts", + "mjs/*.js", + "mjs/*.d.ts", + "ts/*.ts" ], "main": "js/flatbuffers", - "module": "js/flatbuffers.mjs", + "module": "mjs/index.mjs", "directories": { "doc": "docs", "test": "tests" }, "scripts": { - "test": "tests/JavaScriptTest.sh", + "test": "cd tests && ./JavaScriptTest.sh", + "compile-ts": "tsc && tsc -p tsconfig.mjs.json", + "pretest": "npm run compile-ts", "append-esm-export": "sed \"s/this.flatbuffers = flatbuffers;/export { flatbuffers };/\" js/flatbuffers.js > js/flatbuffers.mjs", - "prepublishOnly": "npm run append-esm-export" + "prepublishOnly": "npm run compile-ts && npm run append-esm-export" }, "repository": { "type": "git", @@ -30,5 +35,11 @@ "url": "https://github.com/google/flatbuffers/issues" }, "homepage": "https://google.github.io/flatbuffers/", - "dependencies": {} + "dependencies": {}, + "devDependencies": { + "@typescript-eslint/eslint-plugin": "^4.1.0", + "@typescript-eslint/parser": "^4.1.0", + "eslint": "^7.8.1", + "typescript": "^4.0.2" + } } diff --git a/tests/TypeScriptTest.sh b/tests/TypeScriptTest.sh index 84d2475efa9..f1143545939 100755 --- a/tests/TypeScriptTest.sh +++ b/tests/TypeScriptTest.sh @@ -17,6 +17,7 @@ pushd "$(dirname $0)" >/dev/null npm install @types/flatbuffers +npm run pretest export FB_TS_TEST="TRUE" diff --git a/tests/docker/languages/Dockerfile.testing.node.10_13_0 b/tests/docker/languages/Dockerfile.testing.node.10_13_0 index b821105d1a0..8e48c23cae2 100644 --- a/tests/docker/languages/Dockerfile.testing.node.10_13_0 +++ b/tests/docker/languages/Dockerfile.testing.node.10_13_0 @@ -5,4 +5,6 @@ RUN cp flatc_debian_stretch flatc WORKDIR /code/tests RUN node --version RUN ../flatc -b -I include_test monster_test.fbs unicode_test.json +RUN npm install +RUN npm run pretest RUN node JavaScriptTest ./monster_test_generated diff --git a/tests/docker/languages/Dockerfile.testing.node.11_2_0 b/tests/docker/languages/Dockerfile.testing.node.11_2_0 index f6b48e6e696..090bb457e45 100644 --- a/tests/docker/languages/Dockerfile.testing.node.11_2_0 +++ b/tests/docker/languages/Dockerfile.testing.node.11_2_0 @@ -5,4 +5,6 @@ RUN cp flatc_debian_stretch flatc WORKDIR /code/tests RUN node --version RUN ../flatc -b -I include_test monster_test.fbs unicode_test.json +RUN npm install +RUN npm run pretest RUN node JavaScriptTest ./monster_test_generated diff --git a/ts/builder.ts b/ts/builder.ts new file mode 100644 index 00000000000..6be72fbbed4 --- /dev/null +++ b/ts/builder.ts @@ -0,0 +1,628 @@ +import { ByteBuffer } from "./byte-buffer" +import { SIZEOF_SHORT, SIZE_PREFIX_LENGTH, SIZEOF_INT, FILE_IDENTIFIER_LENGTH } from "./constants" +import { Offset, IGeneratedObject } from "./types" +import { Long } from "./long" + +export class Builder { + private bb: ByteBuffer + /** Remaining space in the ByteBuffer. */ + private space: number + /** Minimum alignment encountered so far. */ + private minalign = 1 + /** The vtable for the current table. */ + private vtable: number[] | null = null + /** The amount of fields we're actually using. */ + private vtable_in_use = 0 + /** Whether we are currently serializing a table. */ + private isNested = false; + /** Starting offset of the current struct/table. */ + private object_start = 0 + /** List of offsets of all vtables. */ + private vtables: number[] = [] + /** For the current vector being built. */ + private vector_num_elems = 0 + /** False omits default values from the serialized data */ + private force_defaults = false; + + private string_maps: Map | null = null; + + /** + * Create a FlatBufferBuilder. + */ + constructor(opt_initial_size?: number) { + let initial_size: number; + + if (!opt_initial_size) { + initial_size = 1024; + } else { + initial_size = opt_initial_size; + } + + /** + * @type {ByteBuffer} + * @private + */ + this.bb = ByteBuffer.allocate(initial_size); + this.space = initial_size; + } + + + clear(): void { + this.bb.clear(); + this.space = this.bb.capacity(); + this.minalign = 1; + this.vtable = null; + this.vtable_in_use = 0; + this.isNested = false; + this.object_start = 0; + this.vtables = []; + this.vector_num_elems = 0; + this.force_defaults = false; + this.string_maps = null; + } + + /** + * In order to save space, fields that are set to their default value + * don't get serialized into the buffer. Forcing defaults provides a + * way to manually disable this optimization. + * + * @param forceDefaults true always serializes default values + */ + forceDefaults(forceDefaults: boolean): void { + this.force_defaults = forceDefaults; + } + + /** + * Get the ByteBuffer representing the FlatBuffer. Only call this after you've + * called finish(). The actual data starts at the ByteBuffer's current position, + * not necessarily at 0. + */ + dataBuffer(): ByteBuffer { + return this.bb; + } + + /** + * Get the bytes representing the FlatBuffer. Only call this after you've + * called finish(). + */ + asUint8Array(): Uint8Array { + return this.bb.bytes().subarray(this.bb.position(), this.bb.position() + this.offset()); + } + + /** + * Prepare to write an element of `size` after `additional_bytes` have been + * written, e.g. if you write a string, you need to align such the int length + * field is aligned to 4 bytes, and the string data follows it directly. If all + * you need to do is alignment, `additional_bytes` will be 0. + * + * @param size This is the of the new element to write + * @param additional_bytes The padding size + */ + prep(size: number, additional_bytes: number): void { + // Track the biggest thing we've ever aligned to. + if (size > this.minalign) { + this.minalign = size; + } + + // Find the amount of alignment needed such that `size` is properly + // aligned after `additional_bytes` + const align_size = ((~(this.bb.capacity() - this.space + additional_bytes)) + 1) & (size - 1); + + // Reallocate the buffer if needed. + while (this.space < align_size + size + additional_bytes) { + const old_buf_size = this.bb.capacity(); + this.bb = Builder.growByteBuffer(this.bb); + this.space += this.bb.capacity() - old_buf_size; + } + + this.pad(align_size); + } + + pad(byte_size: number): void { + for (let i = 0; i < byte_size; i++) { + this.bb.writeInt8(--this.space, 0); + } + } + + writeInt8(value: number): void { + this.bb.writeInt8(this.space -= 1, value); + } + + writeInt16(value: number): void { + this.bb.writeInt16(this.space -= 2, value); + } + + writeInt32(value: number): void { + this.bb.writeInt32(this.space -= 4, value); + } + + writeInt64(value: Long): void { + this.bb.writeInt64(this.space -= 8, value); + } + + writeFloat32(value: number): void { + this.bb.writeFloat32(this.space -= 4, value); + } + + writeFloat64(value: number): void { + this.bb.writeFloat64(this.space -= 8, value); + } + + /** + * Add an `int8` to the buffer, properly aligned, and grows the buffer (if necessary). + * @param value The `int8` to add the the buffer. + */ + addInt8(value: number): void { + this.prep(1, 0); + this.writeInt8(value); + } + + /** + * Add an `int16` to the buffer, properly aligned, and grows the buffer (if necessary). + * @param value The `int16` to add the the buffer. + */ + addInt16(value: number): void { + this.prep(2, 0); + this.writeInt16(value); + } + + /** + * Add an `int32` to the buffer, properly aligned, and grows the buffer (if necessary). + * @param value The `int32` to add the the buffer. + */ + addInt32(value: number): void { + this.prep(4, 0); + this.writeInt32(value); + } + + /** + * Add an `int64` to the buffer, properly aligned, and grows the buffer (if necessary). + * @param value The `int64` to add the the buffer. + */ + addInt64(value: Long): void { + this.prep(8, 0); + this.writeInt64(value); + } + + /** + * Add a `float32` to the buffer, properly aligned, and grows the buffer (if necessary). + * @param value The `float32` to add the the buffer. + */ + addFloat32(value: number): void { + this.prep(4, 0); + this.writeFloat32(value); + } + + /** + * Add a `float64` to the buffer, properly aligned, and grows the buffer (if necessary). + * @param value The `float64` to add the the buffer. + */ + addFloat64(value: number): void { + this.prep(8, 0); + this.writeFloat64(value); + } + + addFieldInt8(voffset: number, value: number, defaultValue: number): void { + if (this.force_defaults || value != defaultValue) { + this.addInt8(value); + this.slot(voffset); + } + } + + addFieldInt16(voffset: number, value: number, defaultValue: number): void { + if (this.force_defaults || value != defaultValue) { + this.addInt16(value); + this.slot(voffset); + } + } + + addFieldInt32(voffset: number, value: number, defaultValue: number): void { + if (this.force_defaults || value != defaultValue) { + this.addInt32(value); + this.slot(voffset); + } + } + + addFieldInt64(voffset: number, value: Long, defaultValue: Long): void { + if (this.force_defaults || !value.equals(defaultValue)) { + this.addInt64(value); + this.slot(voffset); + } + } + + addFieldFloat32(voffset: number, value: number, defaultValue: number): void { + if (this.force_defaults || value != defaultValue) { + this.addFloat32(value); + this.slot(voffset); + } + } + + addFieldFloat64(voffset: number, value: number, defaultValue: number): void { + if (this.force_defaults || value != defaultValue) { + this.addFloat64(value); + this.slot(voffset); + } + } + + addFieldOffset(voffset: number, value: Offset, defaultValue: Offset): void { + if (this.force_defaults || value != defaultValue) { + this.addOffset(value); + this.slot(voffset); + } + } + + /** + * Structs are stored inline, so nothing additional is being added. `d` is always 0. + */ + addFieldStruct(voffset: number, value: Offset, defaultValue: Offset): void { + if (value != defaultValue) { + this.nested(value); + this.slot(voffset); + } + } + + /** + * Structures are always stored inline, they need to be created right + * where they're used. You'll get this assertion failure if you + * created it elsewhere. + */ + nested(obj: Offset): void { + if (obj != this.offset()) { + throw new Error('FlatBuffers: struct must be serialized inline.'); + } + } + + /** + * Should not be creating any other object, string or vector + * while an object is being constructed + */ + notNested(): void { + if (this.isNested) { + throw new Error('FlatBuffers: object serialization must not be nested.'); + } + } + + /** + * Set the current vtable at `voffset` to the current location in the buffer. + */ + slot(voffset: number): void { + if (this.vtable !== null) + this.vtable[voffset] = this.offset(); + } + + /** + * @returns Offset relative to the end of the buffer. + */ + offset(): Offset { + return this.bb.capacity() - this.space; + } + + /** + * Doubles the size of the backing ByteBuffer and copies the old data towards + * the end of the new buffer (since we build the buffer backwards). + * + * @param bb The current buffer with the existing data + * @returns A new byte buffer with the old data copied + * to it. The data is located at the end of the buffer. + * + * uint8Array.set() formally takes {Array|ArrayBufferView}, so to pass + * it a uint8Array we need to suppress the type check: + * @suppress {checkTypes} + */ + static growByteBuffer(bb: ByteBuffer): ByteBuffer { + const old_buf_size = bb.capacity(); + + // Ensure we don't grow beyond what fits in an int. + if (old_buf_size & 0xC0000000) { + throw new Error('FlatBuffers: cannot grow buffer beyond 2 gigabytes.'); + } + + const new_buf_size = old_buf_size << 1; + const nbb = ByteBuffer.allocate(new_buf_size); + nbb.setPosition(new_buf_size - old_buf_size); + nbb.bytes().set(bb.bytes(), new_buf_size - old_buf_size); + return nbb; + } + + /** + * Adds on offset, relative to where it will be written. + * + * @param offset The offset to add. + */ + addOffset(offset: Offset): void { + this.prep(SIZEOF_INT, 0); // Ensure alignment is already done. + this.writeInt32(this.offset() - offset + SIZEOF_INT); + } + + /** + * Start encoding a new object in the buffer. Users will not usually need to + * call this directly. The FlatBuffers compiler will generate helper methods + * that call this method internally. + */ + startObject(numfields: number): void { + this.notNested(); + if (this.vtable == null) { + this.vtable = []; + } + this.vtable_in_use = numfields; + for (let i = 0; i < numfields; i++) { + this.vtable[i] = 0; // This will push additional elements as needed + } + this.isNested = true; + this.object_start = this.offset(); + } + + /** + * Finish off writing the object that is under construction. + * + * @returns The offset to the object inside `dataBuffer` + */ + endObject(): Offset { + if (this.vtable == null || !this.isNested) { + throw new Error('FlatBuffers: endObject called without startObject'); + } + + this.addInt32(0); + const vtableloc = this.offset(); + + // Trim trailing zeroes. + let i = this.vtable_in_use - 1; + // eslint-disable-next-line no-empty + for (; i >= 0 && this.vtable[i] == 0; i--) {} + const trimmed_size = i + 1; + + // Write out the current vtable. + for (; i >= 0; i--) { + // Offset relative to the start of the table. + this.addInt16(this.vtable[i] != 0 ? vtableloc - this.vtable[i] : 0); + } + + const standard_fields = 2; // The fields below: + this.addInt16(vtableloc - this.object_start); + const len = (trimmed_size + standard_fields) * SIZEOF_SHORT; + this.addInt16(len); + + // Search for an existing vtable that matches the current one. + let existing_vtable = 0; + const vt1 = this.space; + outer_loop: + for (i = 0; i < this.vtables.length; i++) { + const vt2 = this.bb.capacity() - this.vtables[i]; + if (len == this.bb.readInt16(vt2)) { + for (let j = SIZEOF_SHORT; j < len; j += SIZEOF_SHORT) { + if (this.bb.readInt16(vt1 + j) != this.bb.readInt16(vt2 + j)) { + continue outer_loop; + } + } + existing_vtable = this.vtables[i]; + break; + } + } + + if (existing_vtable) { + // Found a match: + // Remove the current vtable. + this.space = this.bb.capacity() - vtableloc; + + // Point table to existing vtable. + this.bb.writeInt32(this.space, existing_vtable - vtableloc); + } else { + // No match: + // Add the location of the current vtable to the list of vtables. + this.vtables.push(this.offset()); + + // Point table to current vtable. + this.bb.writeInt32(this.bb.capacity() - vtableloc, this.offset() - vtableloc); + } + + this.isNested = false; + return vtableloc as Offset; + } + + /** + * Finalize a buffer, poiting to the given `root_table`. + */ + finish(root_table: Offset, opt_file_identifier?: string, opt_size_prefix?: boolean): void { + const size_prefix = opt_size_prefix ? SIZE_PREFIX_LENGTH : 0; + if (opt_file_identifier) { + const file_identifier = opt_file_identifier; + this.prep(this.minalign, SIZEOF_INT + + FILE_IDENTIFIER_LENGTH + size_prefix); + if (file_identifier.length != FILE_IDENTIFIER_LENGTH) { + throw new Error('FlatBuffers: file identifier must be length ' + + FILE_IDENTIFIER_LENGTH); + } + for (let i = FILE_IDENTIFIER_LENGTH - 1; i >= 0; i--) { + this.writeInt8(file_identifier.charCodeAt(i)); + } + } + this.prep(this.minalign, SIZEOF_INT + size_prefix); + this.addOffset(root_table); + if (size_prefix) { + this.addInt32(this.bb.capacity() - this.space); + } + this.bb.setPosition(this.space); + } + + /** + * Finalize a size prefixed buffer, pointing to the given `root_table`. + */ + finishSizePrefixed(this: Builder, root_table: Offset, opt_file_identifier?: string): void { + this.finish(root_table, opt_file_identifier, true); + } + + /** + * This checks a required field has been set in a given table that has + * just been constructed. + */ + requiredField(table: Offset, field: number): void { + const table_start = this.bb.capacity() - table; + const vtable_start = table_start - this.bb.readInt32(table_start); + const ok = this.bb.readInt16(vtable_start + field) != 0; + + // If this fails, the caller will show what field needs to be set. + if (!ok) { + throw new Error('FlatBuffers: field ' + field + ' must be set'); + } + } + + /** + * Start a new array/vector of objects. Users usually will not call + * this directly. The FlatBuffers compiler will create a start/end + * method for vector types in generated code. + * + * @param elem_size The size of each element in the array + * @param num_elems The number of elements in the array + * @param alignment The alignment of the array + */ + startVector(elem_size: number, num_elems: number, alignment: number): void { + this.notNested(); + this.vector_num_elems = num_elems; + this.prep(SIZEOF_INT, elem_size * num_elems); + this.prep(alignment, elem_size * num_elems); // Just in case alignment > int. + } + + /** + * Finish off the creation of an array and all its elements. The array must be + * created with `startVector`. + * + * @returns The offset at which the newly created array + * starts. + */ + endVector(): Offset { + this.writeInt32(this.vector_num_elems); + return this.offset(); + } + + /** + * Encode the string `s` in the buffer using UTF-8. If the string passed has + * already been seen, we return the offset of the already written string + * + * @param s The string to encode + * @return The offset in the buffer where the encoded string starts + */ + createSharedString(s: string | Uint8Array): Offset { + if (!s) { return 0 } + + if (!this.string_maps) { + this.string_maps = new Map(); + } + + if (this.string_maps.has(s)) { + return this.string_maps.get(s) as Offset + } + const offset = this.createString(s) + this.string_maps.set(s, offset) + return offset + } + + /** + * Encode the string `s` in the buffer using UTF-8. If a Uint8Array is passed + * instead of a string, it is assumed to contain valid UTF-8 encoded data. + * + * @param s The string to encode + * @return The offset in the buffer where the encoded string starts + */ + createString(s: string | Uint8Array): Offset { + if (!s) { return 0 } + let utf8: string | Uint8Array | number[]; + if (s instanceof Uint8Array) { + utf8 = s; + } else { + utf8 = []; + let i = 0; + + while (i < s.length) { + let codePoint; + + // Decode UTF-16 + const a = s.charCodeAt(i++); + if (a < 0xD800 || a >= 0xDC00) { + codePoint = a; + } else { + const b = s.charCodeAt(i++); + codePoint = (a << 10) + b + (0x10000 - (0xD800 << 10) - 0xDC00); + } + + // Encode UTF-8 + if (codePoint < 0x80) { + utf8.push(codePoint); + } else { + if (codePoint < 0x800) { + utf8.push(((codePoint >> 6) & 0x1F) | 0xC0); + } else { + if (codePoint < 0x10000) { + utf8.push(((codePoint >> 12) & 0x0F) | 0xE0); + } else { + utf8.push( + ((codePoint >> 18) & 0x07) | 0xF0, + ((codePoint >> 12) & 0x3F) | 0x80); + } + utf8.push(((codePoint >> 6) & 0x3F) | 0x80); + } + utf8.push((codePoint & 0x3F) | 0x80); + } + } + } + + this.addInt8(0); + this.startVector(1, utf8.length, 1); + this.bb.setPosition(this.space -= utf8.length); + for (let i = 0, offset = this.space, bytes = this.bb.bytes(); i < utf8.length; i++) { + bytes[offset++] = utf8[i]; + } + return this.endVector(); + } + + /** + * A helper function to avoid generated code depending on this file directly. + */ + createLong(low: number, high: number): Long { + return Long.create(low, high); + } + + /** + * A helper function to pack an object + * + * @returns offset of obj + */ + createObjectOffset(obj: string | IGeneratedObject): Offset { + if(obj === null) { + return 0 + } + + if(typeof obj === 'string') { + return this.createString(obj); + } else { + return obj.pack(this); + } + } + + /** + * A helper function to pack a list of object + * + * @returns list of offsets of each non null object + */ + createObjectOffsetList(list: string[]): Offset[] { + const ret = []; + + for(let i = 0; i < list.length; ++i) { + const val = list[i]; + + if(val !== null) { + ret.push(this.createObjectOffset(val)); + } else { + throw new Error( + 'FlatBuffers: Argument for createObjectOffsetList cannot contain null.'); + } + } + + return ret; + } + + createStructOffsetList(list: string[], startFunc: (builder: Builder, length: number) => void): Offset { + startFunc(this, list.length); + this.createObjectOffsetList(list); + return this.endVector(); + } + } \ No newline at end of file diff --git a/ts/byte-buffer.ts b/ts/byte-buffer.ts new file mode 100644 index 00000000000..b936c7b41b5 --- /dev/null +++ b/ts/byte-buffer.ts @@ -0,0 +1,351 @@ +import { FILE_IDENTIFIER_LENGTH, SIZEOF_INT } from "./constants"; +import { Long } from "./long"; +import { int32, isLittleEndian, float32, float64 } from "./utils"; +import { Offset, Table, IGeneratedObject } from "./types"; +import { Encoding } from "./encoding"; + +export class ByteBuffer { + private position_ = 0; + + /** + * Create a new ByteBuffer with a given array of bytes (`Uint8Array`) + */ + constructor(private bytes_: Uint8Array) { } + + /** + * Create and allocate a new ByteBuffer with a given size. + */ + static allocate(byte_size: number): ByteBuffer { + return new ByteBuffer(new Uint8Array(byte_size)); + } + + clear(): void { + this.position_ = 0; + } + + /** + * Get the underlying `Uint8Array`. + */ + bytes(): Uint8Array { + return this.bytes_; + } + + /** + * Get the buffer's position. + */ + position(): number { + return this.position_; + } + + /** + * Set the buffer's position. + */ + setPosition(position: number): void { + this.position_ = position; + } + + /** + * Get the buffer's capacity. + */ + capacity(): number { + return this.bytes_.length; + } + + readInt8(offset: number): number { + return this.readUint8(offset) << 24 >> 24; + } + + readUint8(offset: number): number { + return this.bytes_[offset]; + } + + readInt16(offset: number): number { + return this.readUint16(offset) << 16 >> 16; + } + + readUint16(offset: number): number { + return this.bytes_[offset] | this.bytes_[offset + 1] << 8; + } + + readInt32(offset: number): number { + return this.bytes_[offset] | this.bytes_[offset + 1] << 8 | this.bytes_[offset + 2] << 16 | this.bytes_[offset + 3] << 24; + } + + readUint32(offset: number): number { + return this.readInt32(offset) >>> 0; + } + + readInt64(offset: number): Long { + return new Long(this.readInt32(offset), this.readInt32(offset + 4)); + } + + readUint64(offset: number): Long { + return new Long(this.readUint32(offset), this.readUint32(offset + 4)); + } + + readFloat32(offset: number): number { + int32[0] = this.readInt32(offset); + return float32[0]; + } + + readFloat64(offset: number): number { + int32[isLittleEndian ? 0 : 1] = this.readInt32(offset); + int32[isLittleEndian ? 1 : 0] = this.readInt32(offset + 4); + return float64[0]; + } + + writeInt8(offset: number, value: number): void { + this.bytes_[offset] = value; + } + + writeUint8(offset: number, value: number): void { + this.bytes_[offset] = value; + } + + writeInt16(offset: number, value: number): void { + this.bytes_[offset] = value; + this.bytes_[offset + 1] = value >> 8; + } + + writeUint16(offset: number, value: number): void { + this.bytes_[offset] = value; + this.bytes_[offset + 1] = value >> 8; + } + + writeInt32(offset: number, value: number): void { + this.bytes_[offset] = value; + this.bytes_[offset + 1] = value >> 8; + this.bytes_[offset + 2] = value >> 16; + this.bytes_[offset + 3] = value >> 24; + } + + writeUint32(offset: number, value: number): void { + this.bytes_[offset] = value; + this.bytes_[offset + 1] = value >> 8; + this.bytes_[offset + 2] = value >> 16; + this.bytes_[offset + 3] = value >> 24; + } + + writeInt64(offset: number, value: Long): void { + this.writeInt32(offset, value.low); + this.writeInt32(offset + 4, value.high); + } + + writeUint64(offset: number, value: Long): void { + this.writeUint32(offset, value.low); + this.writeUint32(offset + 4, value.high); + } + + writeFloat32(offset: number, value: number): void { + float32[0] = value; + this.writeInt32(offset, int32[0]); + } + + writeFloat64(offset: number, value: number): void { + float64[0] = value; + this.writeInt32(offset, int32[isLittleEndian ? 0 : 1]); + this.writeInt32(offset + 4, int32[isLittleEndian ? 1 : 0]); + } + + /** + * Return the file identifier. Behavior is undefined for FlatBuffers whose + * schema does not include a file_identifier (likely points at padding or the + * start of a the root vtable). + */ + getBufferIdentifier(): string { + if (this.bytes_.length < this.position_ + SIZEOF_INT + + FILE_IDENTIFIER_LENGTH) { + throw new Error( + 'FlatBuffers: ByteBuffer is too short to contain an identifier.'); + } + let result = ""; + for (let i = 0; i < FILE_IDENTIFIER_LENGTH; i++) { + result += String.fromCharCode( + this.readInt8(this.position_ + SIZEOF_INT + i)); + } + return result; + } + + /** + * Look up a field in the vtable, return an offset into the object, or 0 if the + * field is not present. + */ + __offset(bb_pos: number, vtable_offset: number): Offset { + const vtable = bb_pos - this.readInt32(bb_pos); + return vtable_offset < this.readInt16(vtable) ? this.readInt16(vtable + vtable_offset) : 0; + } + + /** + * Initialize any Table-derived type to point to the union at the given offset. + */ + __union(t: Table, offset: number): Table { + t.bb_pos = offset + this.readInt32(offset); + t.bb = this; + return t; + } + + /** + * Create a JavaScript string from UTF-8 data stored inside the FlatBuffer. + * This allocates a new string and converts to wide chars upon each access. + * + * To avoid the conversion to UTF-16, pass Encoding.UTF8_BYTES as + * the "optionalEncoding" argument. This is useful for avoiding conversion to + * and from UTF-16 when the data will just be packaged back up in another + * FlatBuffer later on. + * + * @param offset + * @param opt_encoding Defaults to UTF16_STRING + */ + __string(offset: number, opt_encoding?: Encoding): string | Uint8Array { + offset += this.readInt32(offset); + + const length = this.readInt32(offset); + let result = ''; + let i = 0; + + offset += SIZEOF_INT; + + if (opt_encoding === Encoding.UTF8_BYTES) { + return this.bytes_.subarray(offset, offset + length); + } + + while (i < length) { + let codePoint; + + // Decode UTF-8 + const a = this.readUint8(offset + i++); + if (a < 0xC0) { + codePoint = a; + } else { + const b = this.readUint8(offset + i++); + if (a < 0xE0) { + codePoint = + ((a & 0x1F) << 6) | + (b & 0x3F); + } else { + const c = this.readUint8(offset + i++); + if (a < 0xF0) { + codePoint = + ((a & 0x0F) << 12) | + ((b & 0x3F) << 6) | + (c & 0x3F); + } else { + const d = this.readUint8(offset + i++); + codePoint = + ((a & 0x07) << 18) | + ((b & 0x3F) << 12) | + ((c & 0x3F) << 6) | + (d & 0x3F); + } + } + } + + // Encode UTF-16 + if (codePoint < 0x10000) { + result += String.fromCharCode(codePoint); + } else { + codePoint -= 0x10000; + result += String.fromCharCode( + (codePoint >> 10) + 0xD800, + (codePoint & ((1 << 10) - 1)) + 0xDC00); + } + } + + return result; + } + + /** + * Handle unions that can contain string as its member, if a Table-derived type then initialize it, + * if a string then return a new one + * + * WARNING: strings are immutable in JS so we can't change the string that the user gave us, this + * makes the behaviour of __union_with_string different compared to __union + */ + __union_with_string(o: Table | string, offset: number) : Table | string { + if(typeof o === 'string') { + return this.__string(offset) as string; + } + return this.__union(o, offset); + } + + /** + * Retrieve the relative offset stored at "offset" + */ + __indirect(offset: Offset): Offset { + return offset + this.readInt32(offset); + } + + /** + * Get the start of data of a vector whose offset is stored at "offset" in this object. + */ + __vector(offset: Offset): Offset { + return offset + this.readInt32(offset) + SIZEOF_INT; // data starts after the length + } + + /** + * Get the length of a vector whose offset is stored at "offset" in this object. + */ + __vector_len(offset: Offset): Offset { + return this.readInt32(offset + this.readInt32(offset)); + } + + __has_identifier(ident: string): boolean { + if (ident.length != FILE_IDENTIFIER_LENGTH) { + throw new Error('FlatBuffers: file identifier must be length ' + + FILE_IDENTIFIER_LENGTH); + } + for (let i = 0; i < FILE_IDENTIFIER_LENGTH; i++) { + if (ident.charCodeAt(i) != this.readInt8(this.position() + SIZEOF_INT + i)) { + return false; + } + } + return true; + } + + /** + * A helper function to avoid generated code depending on this file directly. + */ + createLong(low: number, high: number): Long { + return Long.create(low, high); + } + + /** + * A helper function for generating list for obj api + */ + createScalarList(listAccessor: (i: number) => unknown, listLength: number) : unknown[] { + const ret: unknown[] = []; + for(let i = 0; i < listLength; ++i) { + if(listAccessor(i) !== null) { + ret.push(listAccessor(i)); + } + } + + return ret; + } + + /** + * This function is here only to get around typescript type system + */ + createStringList(listAccessor: (i: number) => unknown, listLength: number): unknown[] { + return this.createScalarList(listAccessor, listLength); + } + + /** + * A helper function for generating list for obj api + * @param listAccessor function that accepts an index and return data at that index + * @param listLength listLength + * @param res result list + */ + createObjList(listAccessor: (i: number) => IGeneratedObject, listLength: number): IGeneratedObject[] { + const ret: IGeneratedObject[] = []; + for(let i = 0; i < listLength; ++i) { + const val = listAccessor(i); + if(val !== null) { + ret.push(val.unpack()); + } + } + + return ret; + } + + } \ No newline at end of file diff --git a/ts/constants.ts b/ts/constants.ts new file mode 100644 index 00000000000..04510fbcf76 --- /dev/null +++ b/ts/constants.ts @@ -0,0 +1,4 @@ +export const SIZEOF_SHORT = 2; +export const SIZEOF_INT = 4; +export const FILE_IDENTIFIER_LENGTH = 4; +export const SIZE_PREFIX_LENGTH = 4; \ No newline at end of file diff --git a/ts/encoding.ts b/ts/encoding.ts new file mode 100644 index 00000000000..856792ce207 --- /dev/null +++ b/ts/encoding.ts @@ -0,0 +1,4 @@ +export enum Encoding { + UTF8_BYTES = 1, + UTF16_STRING = 2 +} \ No newline at end of file diff --git a/ts/flatbuffers.ts b/ts/flatbuffers.ts new file mode 100644 index 00000000000..2c2a295ebe0 --- /dev/null +++ b/ts/flatbuffers.ts @@ -0,0 +1,33 @@ +/* eslint-disable @typescript-eslint/no-namespace */ +import * as constants from './constants' +import * as types from './types' +import * as utils from './utils' + +import { Long as LongClass } from './long' +import { Encoding as EncodingEnum } from './encoding' +import { Builder as BuilderClass } from './builder' +import { ByteBuffer as ByteBufferClass } from './byte-buffer' + +export namespace flatbuffers { + + export type Offset = types.Offset; + + export type Table = types.Table; + + export const SIZEOF_SHORT = constants.SIZEOF_SHORT; + export const SIZEOF_INT = constants.SIZEOF_INT; + export const FILE_IDENTIFIER_LENGTH = constants.FILE_IDENTIFIER_LENGTH; + export const SIZE_PREFIX_LENGTH = constants.SIZE_PREFIX_LENGTH; + + export const Encoding = EncodingEnum; + + export const int32 = utils.int32; + export const float32 = utils.float32; + export const float64 = utils.float64; + export const isLittleEndian = utils.isLittleEndian; + + export const Long = LongClass; + export const Builder = BuilderClass; + export const ByteBuffer = ByteBufferClass; +} + diff --git a/ts/long.ts b/ts/long.ts new file mode 100644 index 00000000000..50a3ea87fb6 --- /dev/null +++ b/ts/long.ts @@ -0,0 +1,23 @@ +export function createLong(low: number, high: number): Long { + return Long.create(low, high); +} + +export class Long { + static readonly ZERO = new Long(0, 0) + low: number + high: number + constructor(low: number, high: number) { + this.low = low | 0; + this.high = high | 0; + } + static create(low: number, high: number): Long { + // Special-case zero to avoid GC overhead for default values + return low == 0 && high == 0 ? Long.ZERO : new Long(low, high); + } + toFloat64(): number { + return (this.low >>> 0) + this.high * 0x100000000; + } + equals(other: Long): boolean { + return this.low == other.low && this.high == other.high; + } +} \ No newline at end of file diff --git a/ts/types.ts b/ts/types.ts new file mode 100644 index 00000000000..30e40500781 --- /dev/null +++ b/ts/types.ts @@ -0,0 +1,14 @@ +import { ByteBuffer } from './byte-buffer' +import { Builder } from './builder' + +export type Offset = number; + +export type Table = { + bb: ByteBuffer + bb_pos: number +}; + +export interface IGeneratedObject { + pack(builder:Builder): Offset + unpack(): IGeneratedObject +} \ No newline at end of file diff --git a/ts/utils.ts b/ts/utils.ts new file mode 100644 index 00000000000..a2902e3cf6b --- /dev/null +++ b/ts/utils.ts @@ -0,0 +1,4 @@ +export const int32 = new Int32Array(2); +export const float32 = new Float32Array(int32.buffer); +export const float64 = new Float64Array(int32.buffer); +export const isLittleEndian = new Uint16Array(new Uint8Array([1, 0]).buffer)[0] === 1; \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000000..0e4fdc4de7b --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "target": "es5", + "module": "commonjs", + "lib": ["es2015"], + "declaration": true, + "outDir": "./js", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true + }, + "include": [ + "ts/*.ts" + ] +} diff --git a/tsconfig.mjs.json b/tsconfig.mjs.json new file mode 100644 index 00000000000..a887a1c31ee --- /dev/null +++ b/tsconfig.mjs.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "target": "ES2017", + "module": "ES2015", + "lib": ["ES2017"], + "declaration": true, + "outDir": "./mjs", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true + }, + "include": [ + "ts/*.ts" + ] +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 00000000000..0ec94ddc179 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,956 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/code-frame@^7.0.0": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" + integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== + dependencies: + "@babel/highlight" "^7.10.4" + +"@babel/helper-validator-identifier@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" + integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== + +"@babel/highlight@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" + integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== + dependencies: + "@babel/helper-validator-identifier" "^7.10.4" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@eslint/eslintrc@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.1.3.tgz#7d1a2b2358552cc04834c0979bd4275362e37085" + integrity sha512-4YVwPkANLeNtRjMekzux1ci8hIaH5eGKktGqR0d3LWsKNn5B2X/1Z6Trxy7jQXl9EBGE6Yj02O+t09FMeRllaA== + dependencies: + ajv "^6.12.4" + debug "^4.1.1" + espree "^7.3.0" + globals "^12.1.0" + ignore "^4.0.6" + import-fresh "^3.2.1" + js-yaml "^3.13.1" + lodash "^4.17.19" + minimatch "^3.0.4" + strip-json-comments "^3.1.1" + +"@nodelib/fs.scandir@2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" + integrity sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw== + dependencies: + "@nodelib/fs.stat" "2.0.3" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.3", "@nodelib/fs.stat@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz#34dc5f4cabbc720f4e60f75a747e7ecd6c175bd3" + integrity sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz#011b9202a70a6366e436ca5c065844528ab04976" + integrity sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ== + dependencies: + "@nodelib/fs.scandir" "2.1.3" + fastq "^1.6.0" + +"@types/color-name@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" + integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== + +"@types/json-schema@^7.0.3": + version "7.0.6" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0" + integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw== + +"@typescript-eslint/eslint-plugin@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.1.0.tgz#7d309f60815ff35e9627ad85e41928d7b7fd443f" + integrity sha512-U+nRJx8XDUqJxYF0FCXbpmD9nWt/xHDDG0zsw1vrVYAmEAuD/r49iowfurjSL2uTA2JsgtpsyG7mjO7PHf2dYw== + dependencies: + "@typescript-eslint/experimental-utils" "4.1.0" + "@typescript-eslint/scope-manager" "4.1.0" + debug "^4.1.1" + functional-red-black-tree "^1.0.1" + regexpp "^3.0.0" + semver "^7.3.2" + tsutils "^3.17.1" + +"@typescript-eslint/experimental-utils@4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.1.0.tgz#263d7225645c09a411c8735eeffd417f50f49026" + integrity sha512-paEYLA37iqRIDPeQwAmoYSiZ3PiHsaAc3igFeBTeqRHgPnHjHLJ9OGdmP6nwAkF65p2QzEsEBtpjNUBWByNWzA== + dependencies: + "@types/json-schema" "^7.0.3" + "@typescript-eslint/scope-manager" "4.1.0" + "@typescript-eslint/types" "4.1.0" + "@typescript-eslint/typescript-estree" "4.1.0" + eslint-scope "^5.0.0" + eslint-utils "^2.0.0" + +"@typescript-eslint/parser@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.1.0.tgz#9b0409411725f14cd7faa81a664e5051225961db" + integrity sha512-hM/WNCQTzDHgS0Ke3cR9zPndL3OTKr9OoN9CL3UqulsAjYDrglSwIIgswSmHBcSbOzLmgaMARwrQEbIumIglvQ== + dependencies: + "@typescript-eslint/scope-manager" "4.1.0" + "@typescript-eslint/types" "4.1.0" + "@typescript-eslint/typescript-estree" "4.1.0" + debug "^4.1.1" + +"@typescript-eslint/scope-manager@4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.1.0.tgz#9e389745ee9cfe12252ed1e9958808abd6b3a683" + integrity sha512-HD1/u8vFNnxwiHqlWKC/Pigdn0Mvxi84Y6GzbZ5f5sbLrFKu0al02573Er+D63Sw67IffVUXR0uR8rpdfdk+vA== + dependencies: + "@typescript-eslint/types" "4.1.0" + "@typescript-eslint/visitor-keys" "4.1.0" + +"@typescript-eslint/types@4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.1.0.tgz#edbd3fec346f34e13ce7aa176b03b497a32c496a" + integrity sha512-rkBqWsO7m01XckP9R2YHVN8mySOKKY2cophGM8K5uDK89ArCgahItQYdbg/3n8xMxzu2elss+an1TphlUpDuJw== + +"@typescript-eslint/typescript-estree@4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.1.0.tgz#394046ead25164494218c0e3d6b960695ea967f6" + integrity sha512-r6et57qqKAWU173nWyw31x7OfgmKfMEcjJl9vlJEzS+kf9uKNRr4AVTRXfTCwebr7bdiVEkfRY5xGnpPaNPe4Q== + dependencies: + "@typescript-eslint/types" "4.1.0" + "@typescript-eslint/visitor-keys" "4.1.0" + debug "^4.1.1" + globby "^11.0.1" + is-glob "^4.0.1" + lodash "^4.17.15" + semver "^7.3.2" + tsutils "^3.17.1" + +"@typescript-eslint/visitor-keys@4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.1.0.tgz#b2d528c9484e7eda1aa4f86ccf0432fb16e4d545" + integrity sha512-+taO0IZGCtCEsuNTTF2Q/5o8+fHrlml8i9YsZt2AiDCdYEJzYlsmRY991l/6f3jNXFyAWepdQj7n8Na6URiDRQ== + dependencies: + "@typescript-eslint/types" "4.1.0" + eslint-visitor-keys "^2.0.0" + +acorn-jsx@^5.2.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b" + integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== + +acorn@^7.4.0: + version "7.4.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.0.tgz#e1ad486e6c54501634c6c397c5c121daa383607c" + integrity sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w== + +ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.4: + version "6.12.4" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.4.tgz#0614facc4522127fa713445c6bfd3ebd376e2234" + integrity sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-colors@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + +ansi-regex@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + +ansi-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" + integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== + +ansi-styles@^3.2.0, ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" + integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== + dependencies: + "@types/color-name" "^1.1.1" + color-convert "^2.0.1" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +astral-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" + integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +chalk@^2.0.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" + integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +cross-spawn@^7.0.2: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +debug@^4.0.1, debug@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" + integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== + dependencies: + ms "^2.1.1" + +deep-is@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + +enquirer@^2.3.5: + version "2.3.6" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" + integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== + dependencies: + ansi-colors "^4.1.1" + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +eslint-scope@^5.0.0, eslint-scope@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.0.tgz#d0f971dfe59c69e0cada684b23d49dbf82600ce5" + integrity sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint-utils@^2.0.0, eslint-utils@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" + integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== + dependencies: + eslint-visitor-keys "^1.1.0" + +eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" + integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== + +eslint-visitor-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" + integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== + +eslint@^7.8.1: + version "7.8.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.8.1.tgz#e59de3573fb6a5be8ff526c791571646d124a8fa" + integrity sha512-/2rX2pfhyUG0y+A123d0ccXtMm7DV7sH1m3lk9nk2DZ2LReq39FXHueR9xZwshE5MdfSf0xunSaMWRqyIA6M1w== + dependencies: + "@babel/code-frame" "^7.0.0" + "@eslint/eslintrc" "^0.1.3" + ajv "^6.10.0" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.0.1" + doctrine "^3.0.0" + enquirer "^2.3.5" + eslint-scope "^5.1.0" + eslint-utils "^2.1.0" + eslint-visitor-keys "^1.3.0" + espree "^7.3.0" + esquery "^1.2.0" + esutils "^2.0.2" + file-entry-cache "^5.0.1" + functional-red-black-tree "^1.0.1" + glob-parent "^5.0.0" + globals "^12.1.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + js-yaml "^3.13.1" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash "^4.17.19" + minimatch "^3.0.4" + natural-compare "^1.4.0" + optionator "^0.9.1" + progress "^2.0.0" + regexpp "^3.1.0" + semver "^7.2.1" + strip-ansi "^6.0.0" + strip-json-comments "^3.1.0" + table "^5.2.3" + text-table "^0.2.0" + v8-compile-cache "^2.0.3" + +espree@^7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.0.tgz#dc30437cf67947cf576121ebd780f15eeac72348" + integrity sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw== + dependencies: + acorn "^7.4.0" + acorn-jsx "^5.2.0" + eslint-visitor-keys "^1.3.0" + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esquery@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.3.1.tgz#b78b5828aa8e214e29fb74c4d5b752e1c033da57" + integrity sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" + integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-glob@^3.1.1: + version "3.2.4" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.4.tgz#d20aefbf99579383e7f3cc66529158c9b98554d3" + integrity sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.0" + merge2 "^1.3.0" + micromatch "^4.0.2" + picomatch "^2.2.1" + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + +fastq@^1.6.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.8.0.tgz#550e1f9f59bbc65fe185cb6a9b4d95357107f481" + integrity sha512-SMIZoZdLh/fgofivvIkmknUXyPnvxRE3DhtZ5Me3Mrsk5gyPL42F0xr51TdRXskBxHfMp+07bcYzfsYEsSQA9Q== + dependencies: + reusify "^1.0.4" + +file-entry-cache@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" + integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== + dependencies: + flat-cache "^2.0.1" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +flat-cache@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" + integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== + dependencies: + flatted "^2.0.0" + rimraf "2.6.3" + write "1.0.3" + +flatted@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" + integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + +glob-parent@^5.0.0, glob-parent@^5.1.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" + integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== + dependencies: + is-glob "^4.0.1" + +glob@^7.1.3: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^12.1.0: + version "12.4.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-12.4.0.tgz#a18813576a41b00a24a97e7f815918c2e19925f8" + integrity sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg== + dependencies: + type-fest "^0.8.1" + +globby@^11.0.1: + version "11.0.1" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.1.tgz#9a2bf107a068f3ffeabc49ad702c79ede8cfd357" + integrity sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.1.1" + ignore "^5.1.4" + merge2 "^1.3.0" + slash "^3.0.0" + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +ignore@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== + +ignore@^5.1.4: + version "5.1.8" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" + integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== + +import-fresh@^3.0.0, import-fresh@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.1.tgz#633ff618506e793af5ac91bf48b72677e15cbe66" + integrity sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-glob@^4.0.0, is-glob@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + dependencies: + is-extglob "^2.1.1" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.14.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482" + integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19: + version "4.17.20" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" + integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== + +merge2@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" + integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== + dependencies: + braces "^3.0.1" + picomatch "^2.0.5" + +minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimist@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + +mkdirp@^0.5.1: + version "0.5.5" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" + integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== + dependencies: + minimist "^1.2.5" + +ms@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +picomatch@^2.0.5, picomatch@^2.2.1: + version "2.2.2" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" + integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +progress@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + +punycode@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +regexpp@^3.0.0, regexpp@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" + integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + +run-parallel@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" + integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== + +semver@^7.2.1, semver@^7.3.2: + version "7.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" + integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +slice-ansi@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" + integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== + dependencies: + ansi-styles "^3.2.0" + astral-regex "^1.0.0" + is-fullwidth-code-point "^2.0.0" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + +string-width@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + +strip-ansi@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + +strip-ansi@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== + dependencies: + ansi-regex "^5.0.0" + +strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +table@^5.2.3: + version "5.4.6" + resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" + integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== + dependencies: + ajv "^6.10.2" + lodash "^4.17.14" + slice-ansi "^2.1.0" + string-width "^3.0.0" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +tslib@^1.8.1: + version "1.13.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" + integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== + +tsutils@^3.17.1: + version "3.17.1" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759" + integrity sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g== + dependencies: + tslib "^1.8.1" + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-fest@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + +typescript@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.2.tgz#7ea7c88777c723c681e33bf7988be5d008d05ac2" + integrity sha512-e4ERvRV2wb+rRZ/IQeb3jm2VxBsirQLpQhdxplZ2MEzGvDkkMmPglecnNDfSUBivMjP93vRbngYYDQqQ/78bcQ== + +uri-js@^4.2.2: + version "4.4.0" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.0.tgz#aa714261de793e8a82347a7bcc9ce74e86f28602" + integrity sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g== + dependencies: + punycode "^2.1.0" + +v8-compile-cache@^2.0.3: + version "2.1.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz#54bc3cdd43317bca91e35dcaf305b1a7237de745" + integrity sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ== + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +word-wrap@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +write@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" + integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== + dependencies: + mkdirp "^0.5.1"