Buckets:
| ; | |
| module.exports = Namespace; | |
| // extends ReflectionObject | |
| var ReflectionObject = require("./object"); | |
| ((Namespace.prototype = Object.create(ReflectionObject.prototype)).constructor = Namespace).className = "Namespace"; | |
| var Field = require("./field"), | |
| util = require("./util"), | |
| OneOf = require("./oneof"); | |
| var Type, // cyclic | |
| Service, | |
| Enum; | |
| /** | |
| * Constructs a new namespace instance. | |
| * @name Namespace | |
| * @classdesc Reflected namespace. | |
| * @extends NamespaceBase | |
| * @constructor | |
| * @param {string} name Namespace name | |
| * @param {Object.<string,*>} [options] Declared options | |
| */ | |
| /** | |
| * Constructs a namespace from JSON. | |
| * @memberof Namespace | |
| * @function | |
| * @param {string} name Namespace name | |
| * @param {Object.<string,*>} json JSON object | |
| * @returns {Namespace} Created namespace | |
| * @throws {TypeError} If arguments are invalid | |
| */ | |
| Namespace.fromJSON = function fromJSON(name, json) { | |
| return new Namespace(name, json.options).addJSON(json.nested); | |
| }; | |
| /** | |
| * Converts an array of reflection objects to JSON. | |
| * @memberof Namespace | |
| * @param {ReflectionObject[]} array Object array | |
| * @param {IToJSONOptions} [toJSONOptions] JSON conversion options | |
| * @returns {Object.<string,*>|undefined} JSON object or `undefined` when array is empty | |
| */ | |
| function arrayToJSON(array, toJSONOptions) { | |
| if (!(array && array.length)) | |
| return undefined; | |
| var obj = {}; | |
| for (var i = 0; i < array.length; ++i) | |
| obj[array[i].name] = array[i].toJSON(toJSONOptions); | |
| return obj; | |
| } | |
| Namespace.arrayToJSON = arrayToJSON; | |
| /** | |
| * Tests if the specified id is reserved. | |
| * @param {Array.<number[]|string>|undefined} reserved Array of reserved ranges and names | |
| * @param {number} id Id to test | |
| * @returns {boolean} `true` if reserved, otherwise `false` | |
| */ | |
| Namespace.isReservedId = function isReservedId(reserved, id) { | |
| if (reserved) | |
| for (var i = 0; i < reserved.length; ++i) | |
| if (typeof reserved[i] !== "string" && reserved[i][0] <= id && reserved[i][1] > id) | |
| return true; | |
| return false; | |
| }; | |
| /** | |
| * Tests if the specified name is reserved. | |
| * @param {Array.<number[]|string>|undefined} reserved Array of reserved ranges and names | |
| * @param {string} name Name to test | |
| * @returns {boolean} `true` if reserved, otherwise `false` | |
| */ | |
| Namespace.isReservedName = function isReservedName(reserved, name) { | |
| if (reserved) | |
| for (var i = 0; i < reserved.length; ++i) | |
| if (reserved[i] === name) | |
| return true; | |
| return false; | |
| }; | |
| /** | |
| * Not an actual constructor. Use {@link Namespace} instead. | |
| * @classdesc Base class of all reflection objects containing nested objects. This is not an actual class but here for the sake of having consistent type definitions. | |
| * @exports NamespaceBase | |
| * @extends ReflectionObject | |
| * @abstract | |
| * @constructor | |
| * @param {string} name Namespace name | |
| * @param {Object.<string,*>} [options] Declared options | |
| * @see {@link Namespace} | |
| */ | |
| function Namespace(name, options) { | |
| ReflectionObject.call(this, name, options); | |
| /** | |
| * Nested objects by name. | |
| * @type {Object.<string,ReflectionObject>|undefined} | |
| */ | |
| this.nested = undefined; // toJSON | |
| /** | |
| * Cached nested objects as an array. | |
| * @type {ReflectionObject[]|null} | |
| * @private | |
| */ | |
| this._nestedArray = null; | |
| /** | |
| * Cache lookup calls for any objects contains anywhere under this namespace. | |
| * This drastically speeds up resolve for large cross-linked protos where the same | |
| * types are looked up repeatedly. | |
| * @type {Object.<string,ReflectionObject|null>} | |
| * @private | |
| */ | |
| this._lookupCache = {}; | |
| /** | |
| * Whether or not objects contained in this namespace need feature resolution. | |
| * @type {boolean} | |
| * @protected | |
| */ | |
| this._needsRecursiveFeatureResolution = true; | |
| /** | |
| * Whether or not objects contained in this namespace need a resolve. | |
| * @type {boolean} | |
| * @protected | |
| */ | |
| this._needsRecursiveResolve = true; | |
| } | |
| function clearCache(namespace) { | |
| namespace._nestedArray = null; | |
| namespace._lookupCache = {}; | |
| // Also clear parent caches, since they include nested lookups. | |
| var parent = namespace; | |
| while(parent = parent.parent) { | |
| parent._lookupCache = {}; | |
| } | |
| return namespace; | |
| } | |
| /** | |
| * Nested objects of this namespace as an array for iteration. | |
| * @name NamespaceBase#nestedArray | |
| * @type {ReflectionObject[]} | |
| * @readonly | |
| */ | |
| Object.defineProperty(Namespace.prototype, "nestedArray", { | |
| get: function() { | |
| return this._nestedArray || (this._nestedArray = util.toArray(this.nested)); | |
| } | |
| }); | |
| /** | |
| * Namespace descriptor. | |
| * @interface INamespace | |
| * @property {Object.<string,*>} [options] Namespace options | |
| * @property {Object.<string,AnyNestedObject>} [nested] Nested object descriptors | |
| */ | |
| /** | |
| * Any extension field descriptor. | |
| * @typedef AnyExtensionField | |
| * @type {IExtensionField|IExtensionMapField} | |
| */ | |
| /** | |
| * Any nested object descriptor. | |
| * @typedef AnyNestedObject | |
| * @type {IEnum|IType|IService|AnyExtensionField|INamespace|IOneOf} | |
| */ | |
| /** | |
| * Converts this namespace to a namespace descriptor. | |
| * @param {IToJSONOptions} [toJSONOptions] JSON conversion options | |
| * @returns {INamespace} Namespace descriptor | |
| */ | |
| Namespace.prototype.toJSON = function toJSON(toJSONOptions) { | |
| return util.toObject([ | |
| "options" , this.options, | |
| "nested" , arrayToJSON(this.nestedArray, toJSONOptions) | |
| ]); | |
| }; | |
| /** | |
| * Adds nested objects to this namespace from nested object descriptors. | |
| * @param {Object.<string,AnyNestedObject>} nestedJson Any nested object descriptors | |
| * @returns {Namespace} `this` | |
| */ | |
| Namespace.prototype.addJSON = function addJSON(nestedJson) { | |
| var ns = this; | |
| /* istanbul ignore else */ | |
| if (nestedJson) { | |
| for (var names = Object.keys(nestedJson), i = 0, nested; i < names.length; ++i) { | |
| nested = nestedJson[names[i]]; | |
| ns.add( // most to least likely | |
| ( nested.fields !== undefined | |
| ? Type.fromJSON | |
| : nested.values !== undefined | |
| ? Enum.fromJSON | |
| : nested.methods !== undefined | |
| ? Service.fromJSON | |
| : nested.id !== undefined | |
| ? Field.fromJSON | |
| : Namespace.fromJSON )(names[i], nested) | |
| ); | |
| } | |
| } | |
| return this; | |
| }; | |
| /** | |
| * Gets the nested object of the specified name. | |
| * @param {string} name Nested object name | |
| * @returns {ReflectionObject|null} The reflection object or `null` if it doesn't exist | |
| */ | |
| Namespace.prototype.get = function get(name) { | |
| return this.nested && this.nested[name] | |
| || null; | |
| }; | |
| /** | |
| * Gets the values of the nested {@link Enum|enum} of the specified name. | |
| * This methods differs from {@link Namespace#get|get} in that it returns an enum's values directly and throws instead of returning `null`. | |
| * @param {string} name Nested enum name | |
| * @returns {Object.<string,number>} Enum values | |
| * @throws {Error} If there is no such enum | |
| */ | |
| Namespace.prototype.getEnum = function getEnum(name) { | |
| if (this.nested && this.nested[name] instanceof Enum) | |
| return this.nested[name].values; | |
| throw Error("no such enum: " + name); | |
| }; | |
| /** | |
| * Adds a nested object to this namespace. | |
| * @param {ReflectionObject} object Nested object to add | |
| * @returns {Namespace} `this` | |
| * @throws {TypeError} If arguments are invalid | |
| * @throws {Error} If there is already a nested object with this name | |
| */ | |
| Namespace.prototype.add = function add(object) { | |
| if (!(object instanceof Field && object.extend !== undefined || object instanceof Type || object instanceof OneOf || object instanceof Enum || object instanceof Service || object instanceof Namespace)) | |
| throw TypeError("object must be a valid nested object"); | |
| if (!this.nested) | |
| this.nested = {}; | |
| else { | |
| var prev = this.get(object.name); | |
| if (prev) { | |
| if (prev instanceof Namespace && object instanceof Namespace && !(prev instanceof Type || prev instanceof Service)) { | |
| // replace plain namespace but keep existing nested elements and options | |
| var nested = prev.nestedArray; | |
| for (var i = 0; i < nested.length; ++i) | |
| object.add(nested[i]); | |
| this.remove(prev); | |
| if (!this.nested) | |
| this.nested = {}; | |
| object.setOptions(prev.options, true); | |
| } else | |
| throw Error("duplicate name '" + object.name + "' in " + this); | |
| } | |
| } | |
| this.nested[object.name] = object; | |
| if (!(this instanceof Type || this instanceof Service || this instanceof Enum || this instanceof Field)) { | |
| // This is a package or a root namespace. | |
| if (!object._edition) { | |
| // Make sure that some edition is set if it hasn't already been specified. | |
| object._edition = object._defaultEdition; | |
| } | |
| } | |
| this._needsRecursiveFeatureResolution = true; | |
| this._needsRecursiveResolve = true; | |
| // Also clear parent caches, since they need to recurse down. | |
| var parent = this; | |
| while(parent = parent.parent) { | |
| parent._needsRecursiveFeatureResolution = true; | |
| parent._needsRecursiveResolve = true; | |
| } | |
| object.onAdd(this); | |
| return clearCache(this); | |
| }; | |
| /** | |
| * Removes a nested object from this namespace. | |
| * @param {ReflectionObject} object Nested object to remove | |
| * @returns {Namespace} `this` | |
| * @throws {TypeError} If arguments are invalid | |
| * @throws {Error} If `object` is not a member of this namespace | |
| */ | |
| Namespace.prototype.remove = function remove(object) { | |
| if (!(object instanceof ReflectionObject)) | |
| throw TypeError("object must be a ReflectionObject"); | |
| if (object.parent !== this) | |
| throw Error(object + " is not a member of " + this); | |
| delete this.nested[object.name]; | |
| if (!Object.keys(this.nested).length) | |
| this.nested = undefined; | |
| object.onRemove(this); | |
| return clearCache(this); | |
| }; | |
| /** | |
| * Defines additial namespaces within this one if not yet existing. | |
| * @param {string|string[]} path Path to create | |
| * @param {*} [json] Nested types to create from JSON | |
| * @returns {Namespace} Pointer to the last namespace created or `this` if path is empty | |
| */ | |
| Namespace.prototype.define = function define(path, json) { | |
| if (util.isString(path)) | |
| path = path.split("."); | |
| else if (!Array.isArray(path)) | |
| throw TypeError("illegal path"); | |
| if (path && path.length && path[0] === "") | |
| throw Error("path must be relative"); | |
| var ptr = this; | |
| while (path.length > 0) { | |
| var part = path.shift(); | |
| if (ptr.nested && ptr.nested[part]) { | |
| ptr = ptr.nested[part]; | |
| if (!(ptr instanceof Namespace)) | |
| throw Error("path conflicts with non-namespace objects"); | |
| } else | |
| ptr.add(ptr = new Namespace(part)); | |
| } | |
| if (json) | |
| ptr.addJSON(json); | |
| return ptr; | |
| }; | |
| /** | |
| * Resolves this namespace's and all its nested objects' type references. Useful to validate a reflection tree, but comes at a cost. | |
| * @returns {Namespace} `this` | |
| */ | |
| Namespace.prototype.resolveAll = function resolveAll() { | |
| if (!this._needsRecursiveResolve) return this; | |
| this._resolveFeaturesRecursive(this._edition); | |
| var nested = this.nestedArray, i = 0; | |
| this.resolve(); | |
| while (i < nested.length) | |
| if (nested[i] instanceof Namespace) | |
| nested[i++].resolveAll(); | |
| else | |
| nested[i++].resolve(); | |
| this._needsRecursiveResolve = false; | |
| return this; | |
| }; | |
| /** | |
| * @override | |
| */ | |
| Namespace.prototype._resolveFeaturesRecursive = function _resolveFeaturesRecursive(edition) { | |
| if (!this._needsRecursiveFeatureResolution) return this; | |
| this._needsRecursiveFeatureResolution = false; | |
| edition = this._edition || edition; | |
| ReflectionObject.prototype._resolveFeaturesRecursive.call(this, edition); | |
| this.nestedArray.forEach(nested => { | |
| nested._resolveFeaturesRecursive(edition); | |
| }); | |
| return this; | |
| }; | |
| /** | |
| * Recursively looks up the reflection object matching the specified path in the scope of this namespace. | |
| * @param {string|string[]} path Path to look up | |
| * @param {*|Array.<*>} filterTypes Filter types, any combination of the constructors of `protobuf.Type`, `protobuf.Enum`, `protobuf.Service` etc. | |
| * @param {boolean} [parentAlreadyChecked=false] If known, whether the parent has already been checked | |
| * @returns {ReflectionObject|null} Looked up object or `null` if none could be found | |
| */ | |
| Namespace.prototype.lookup = function lookup(path, filterTypes, parentAlreadyChecked) { | |
| /* istanbul ignore next */ | |
| if (typeof filterTypes === "boolean") { | |
| parentAlreadyChecked = filterTypes; | |
| filterTypes = undefined; | |
| } else if (filterTypes && !Array.isArray(filterTypes)) | |
| filterTypes = [ filterTypes ]; | |
| if (util.isString(path) && path.length) { | |
| if (path === ".") | |
| return this.root; | |
| path = path.split("."); | |
| } else if (!path.length) | |
| return this; | |
| var flatPath = path.join("."); | |
| // Start at root if path is absolute | |
| if (path[0] === "") | |
| return this.root.lookup(path.slice(1), filterTypes); | |
| // Early bailout for objects with matching absolute paths | |
| var found = this.root._fullyQualifiedObjects && this.root._fullyQualifiedObjects["." + flatPath]; | |
| if (found && (!filterTypes || filterTypes.indexOf(found.constructor) > -1)) { | |
| return found; | |
| } | |
| // Do a regular lookup at this namespace and below | |
| found = this._lookupImpl(path, flatPath); | |
| if (found && (!filterTypes || filterTypes.indexOf(found.constructor) > -1)) { | |
| return found; | |
| } | |
| if (parentAlreadyChecked) | |
| return null; | |
| // If there hasn't been a match, walk up the tree and look more broadly | |
| var current = this; | |
| while (current.parent) { | |
| found = current.parent._lookupImpl(path, flatPath); | |
| if (found && (!filterTypes || filterTypes.indexOf(found.constructor) > -1)) { | |
| return found; | |
| } | |
| current = current.parent; | |
| } | |
| return null; | |
| }; | |
| /** | |
| * Internal helper for lookup that handles searching just at this namespace and below along with caching. | |
| * @param {string[]} path Path to look up | |
| * @param {string} flatPath Flattened version of the path to use as a cache key | |
| * @returns {ReflectionObject|null} Looked up object or `null` if none could be found | |
| * @private | |
| */ | |
| Namespace.prototype._lookupImpl = function lookup(path, flatPath) { | |
| if(Object.prototype.hasOwnProperty.call(this._lookupCache, flatPath)) { | |
| return this._lookupCache[flatPath]; | |
| } | |
| // Test if the first part matches any nested object, and if so, traverse if path contains more | |
| var found = this.get(path[0]); | |
| var exact = null; | |
| if (found) { | |
| if (path.length === 1) { | |
| exact = found; | |
| } else if (found instanceof Namespace) { | |
| path = path.slice(1); | |
| exact = found._lookupImpl(path, path.join(".")); | |
| } | |
| // Otherwise try each nested namespace | |
| } else { | |
| for (var i = 0; i < this.nestedArray.length; ++i) | |
| if (this._nestedArray[i] instanceof Namespace && (found = this._nestedArray[i]._lookupImpl(path, flatPath))) | |
| exact = found; | |
| } | |
| // Set this even when null, so that when we walk up the tree we can quickly bail on repeated checks back down. | |
| this._lookupCache[flatPath] = exact; | |
| return exact; | |
| }; | |
| /** | |
| * Looks up the reflection object at the specified path, relative to this namespace. | |
| * @name NamespaceBase#lookup | |
| * @function | |
| * @param {string|string[]} path Path to look up | |
| * @param {boolean} [parentAlreadyChecked=false] Whether the parent has already been checked | |
| * @returns {ReflectionObject|null} Looked up object or `null` if none could be found | |
| * @variation 2 | |
| */ | |
| // lookup(path: string, [parentAlreadyChecked: boolean]) | |
| /** | |
| * Looks up the {@link Type|type} at the specified path, relative to this namespace. | |
| * Besides its signature, this methods differs from {@link Namespace#lookup|lookup} in that it throws instead of returning `null`. | |
| * @param {string|string[]} path Path to look up | |
| * @returns {Type} Looked up type | |
| * @throws {Error} If `path` does not point to a type | |
| */ | |
| Namespace.prototype.lookupType = function lookupType(path) { | |
| var found = this.lookup(path, [ Type ]); | |
| if (!found) | |
| throw Error("no such type: " + path); | |
| return found; | |
| }; | |
| /** | |
| * Looks up the values of the {@link Enum|enum} at the specified path, relative to this namespace. | |
| * Besides its signature, this methods differs from {@link Namespace#lookup|lookup} in that it throws instead of returning `null`. | |
| * @param {string|string[]} path Path to look up | |
| * @returns {Enum} Looked up enum | |
| * @throws {Error} If `path` does not point to an enum | |
| */ | |
| Namespace.prototype.lookupEnum = function lookupEnum(path) { | |
| var found = this.lookup(path, [ Enum ]); | |
| if (!found) | |
| throw Error("no such Enum '" + path + "' in " + this); | |
| return found; | |
| }; | |
| /** | |
| * Looks up the {@link Type|type} or {@link Enum|enum} at the specified path, relative to this namespace. | |
| * Besides its signature, this methods differs from {@link Namespace#lookup|lookup} in that it throws instead of returning `null`. | |
| * @param {string|string[]} path Path to look up | |
| * @returns {Type} Looked up type or enum | |
| * @throws {Error} If `path` does not point to a type or enum | |
| */ | |
| Namespace.prototype.lookupTypeOrEnum = function lookupTypeOrEnum(path) { | |
| var found = this.lookup(path, [ Type, Enum ]); | |
| if (!found) | |
| throw Error("no such Type or Enum '" + path + "' in " + this); | |
| return found; | |
| }; | |
| /** | |
| * Looks up the {@link Service|service} at the specified path, relative to this namespace. | |
| * Besides its signature, this methods differs from {@link Namespace#lookup|lookup} in that it throws instead of returning `null`. | |
| * @param {string|string[]} path Path to look up | |
| * @returns {Service} Looked up service | |
| * @throws {Error} If `path` does not point to a service | |
| */ | |
| Namespace.prototype.lookupService = function lookupService(path) { | |
| var found = this.lookup(path, [ Service ]); | |
| if (!found) | |
| throw Error("no such Service '" + path + "' in " + this); | |
| return found; | |
| }; | |
| // Sets up cyclic dependencies (called in index-light) | |
| Namespace._configure = function(Type_, Service_, Enum_) { | |
| Type = Type_; | |
| Service = Service_; | |
| Enum = Enum_; | |
| }; | |
Xet Storage Details
- Size:
- 18.6 kB
- Xet hash:
- 61f0159b41d5f7b6716c20719aedbe3744170512707b5ade04a06eea7d5ddadb
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.