From c639014507f08dbbdffecae8ccae0118390d13f8 Mon Sep 17 00:00:00 2001 From: Matthieu Monsch Date: Sat, 14 Aug 2021 08:00:06 -0700 Subject: [PATCH] Allow ignoring namespaces during resolution --- lib/types.js | 30 +++++++++++++++++++++++++----- package.json | 2 +- test/test_types.js | 16 ++++++++++++++++ 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/lib/types.js b/lib/types.js index bbf13fee..ee2f5da4 100644 --- a/lib/types.js +++ b/lib/types.js @@ -1685,11 +1685,11 @@ EnumType.prototype.compare = function (val1, val2) { return utils.compare(this._indices[val1], this._indices[val2]); }; -EnumType.prototype._update = function (resolver, type) { +EnumType.prototype._update = function (resolver, type, opts) { var symbols = this.symbols; if ( type.typeName === 'enum' && - (!type.name || ~getAliases(this).indexOf(type.name)) && + hasCompatibleName(this, type, !opts.ignoreNamespaces) && ( type.symbols.every(function (s) { return ~symbols.indexOf(s); }) || this.default !== undefined @@ -1760,11 +1760,11 @@ FixedType.prototype._match = function (tap1, tap2) { FixedType.prototype.compare = Buffer.compare; -FixedType.prototype._update = function (resolver, type) { +FixedType.prototype._update = function (resolver, type, opts) { if ( type.typeName === 'fixed' && this.size === type.size && - (!type.name || ~getAliases(this).indexOf(type.name)) + hasCompatibleName(this, type, !opts.ignoreNamespaces) ) { resolver.size = this.size; resolver._read = this._read; @@ -2343,7 +2343,7 @@ RecordType.prototype._createWriter = function () { RecordType.prototype._update = function (resolver, type, opts) { // jshint -W054 - if (type.name && !~getAliases(this).indexOf(type.name)) { + if (!hasCompatibleName(this, type, !opts.ignoreNamespaces)) { throw new Error(f('no alias found for %s', type.name)); } @@ -2920,6 +2920,26 @@ function getAliases(obj) { return Object.keys(names); } +/** Checks if a type can be read as another based on name resolution rules. */ +function hasCompatibleName(reader, writer, strict) { + if (!writer.name) { + return true; + } + var name = strict ? writer.name : utils.unqualify(writer.name); + var aliases = getAliases(reader); + var i, l, alias; + for (i = 0, l = aliases.length; i < l; i++) { + alias = aliases[i]; + if (!strict) { + alias = utils.unqualify(alias); + } + if (alias === name) { + return true; + } + } + return false; +} + /** * Check whether a type's name is a primitive. * diff --git a/package.json b/package.json index 85e753a9..a83985e4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "avsc", - "version": "5.7.2", + "version": "5.7.3", "description": "Avro for JavaScript", "homepage": "https://github.com/mtth/avsc", "keywords": [ diff --git a/test/test_types.js b/test/test_types.js index cf6687bc..3988cdfc 100644 --- a/test/test_types.js +++ b/test/test_types.js @@ -3583,6 +3583,22 @@ suite('types', function () { assert.doesNotThrow(function () { t3.createResolver(t1); }); }); + test('ignore namespaces', function () { + var t1 = Type.forSchema({type: 'fixed', name: 'foo.Two', size: 2}); + var t2 = Type.forSchema( + {type: 'fixed', size: 2, name: 'bar.Deux', aliases: ['bar.Two']} + ); + assert.throws(function () { t1.createResolver(t2); }); + assert.doesNotThrow(function () { + t2.createResolver(t1, {ignoreNamespaces: true}); + }); + var t3 = Type.forSchema({type: 'fixed', size: 2, name: 'Two'}); + assert.throws(function () { t3.createResolver(t1); }); + assert.doesNotThrow(function () { + t3.createResolver(t1, {ignoreNamespaces: true}); + }); + }); + }); suite('type references', function () {