diff --git a/index.d.ts b/index.d.ts index 0744761c8..d59825407 100644 --- a/index.d.ts +++ b/index.d.ts @@ -800,9 +800,10 @@ export abstract class NamespaceBase extends ReflectionObject { * @param path Path to look up * @param filterTypes Filter types, any combination of the constructors of `protobuf.Type`, `protobuf.Enum`, `protobuf.Service` etc. * @param [parentAlreadyChecked=false] If known, whether the parent has already been checked + * @param [checkNested=false] @deprecated Whether to include nested objects in the lookup (for backwards-compatibility) * @returns Looked up object or `null` if none could be found */ - public lookup(path: (string|string[]), filterTypes: (any|any[]), parentAlreadyChecked?: boolean): (ReflectionObject|null); + public lookup(path: (string|string[]), filterTypes: (any|any[]), parentAlreadyChecked?: boolean, checkNested?: boolean): (ReflectionObject|null); /** * Looks up the reflection object at the specified path, relative to this namespace. diff --git a/src/namespace.js b/src/namespace.js index 731afc75f..e5c13f8d1 100644 --- a/src/namespace.js +++ b/src/namespace.js @@ -315,9 +315,10 @@ Namespace.prototype.resolveAll = function resolveAll() { * @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 + * @param {boolean} [checkNested=false] @deprecated Whether to include nested objects in the lookup (for backwards-compatibility) * @returns {ReflectionObject|null} Looked up object or `null` if none could be found */ -Namespace.prototype.lookup = function lookup(path, filterTypes, parentAlreadyChecked) { +Namespace.prototype.lookup = function lookup(path, filterTypes, parentAlreadyChecked, checkNested) { /* istanbul ignore next */ if (typeof filterTypes === "boolean") { @@ -326,6 +327,12 @@ Namespace.prototype.lookup = function lookup(path, filterTypes, parentAlreadyChe } else if (filterTypes && !Array.isArray(filterTypes)) filterTypes = [ filterTypes ]; + if (typeof checkNested !== 'boolean') + // Note: adding backwards-compatibility support for resolving non-qualified names using nested namespaces, + // which goes against the protobuf specification. This will only be supported for lookups originating from + // the root namespace now, and fully qualified names should be used instead to avoid ambiguity. + checkNested = this === this.root && path[0] !== '.'; + if (util.isString(path) && path.length) { if (path === ".") return this.root; @@ -335,7 +342,7 @@ Namespace.prototype.lookup = function lookup(path, filterTypes, parentAlreadyChe // Start at root if path is absolute if (path[0] === "") - return this.root.lookup(path.slice(1), filterTypes); + return this.root.lookup(path.slice(1), filterTypes, true, false); // Test if the first part matches any nested object, and if so, traverse if path contains more var found = this.get(path[0]); @@ -343,19 +350,19 @@ Namespace.prototype.lookup = function lookup(path, filterTypes, parentAlreadyChe if (path.length === 1) { if (!filterTypes || filterTypes.indexOf(found.constructor) > -1) return found; - } else if (found instanceof Namespace && (found = found.lookup(path.slice(1), filterTypes, true))) + } else if (found instanceof Namespace && (found = found.lookup(path.slice(1), filterTypes, true, false))) return found; // Otherwise try each nested namespace - } else + } else if (checkNested) for (var i = 0; i < this.nestedArray.length; ++i) - if (this._nestedArray[i] instanceof Namespace && (found = this._nestedArray[i].lookup(path, filterTypes, true))) + if (this._nestedArray[i] instanceof Namespace && (found = this._nestedArray[i].lookup(path, filterTypes, true, true))) return found; // If there hasn't been a match, try again at the parent if (this.parent === null || parentAlreadyChecked) return null; - return this.parent.lookup(path, filterTypes); + return this.parent.lookup(path, filterTypes, false, false); }; /** diff --git a/tests/api_namespace.js b/tests/api_namespace.js index b7203da68..12dbdd663 100644 --- a/tests/api_namespace.js +++ b/tests/api_namespace.js @@ -11,6 +11,7 @@ enum Enm {\ }\ message Msg {\ message Enm {}\ + message Inner {}\ }\ service Svc {}"; @@ -35,6 +36,10 @@ tape.test("reflected namespaces", function(test) { test.equal(ns.get("Msg").lookupTypeOrEnum("Enm"), ns.lookup(".ns.Msg.Enm"), "should lookup the nearest type or enum"); + test.throws(function() { + ns.lookupType("Inner"); + }, Error, "should throw when looking up an inner nested type without specifying its path"); + test.throws(function() { ns.lookupType("Enm"); }, Error, "should throw when looking up an enum as a type");