From ef24ae4e93cf8635ff38398b37f3597e5d478330 Mon Sep 17 00:00:00 2001 From: Alexander Fenster Date: Fri, 26 Aug 2022 12:56:02 -0700 Subject: [PATCH] feat: accept unknown enum values in fromObject (#1793) * feat: accept unknown enum values in fromObject * fix: lint --- src/converter.js | 12 +++++++++--- tests/api_converters.js | 7 ++++--- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/converter.js b/src/converter.js index d0467dcd2..a043ceef8 100644 --- a/src/converter.js +++ b/src/converter.js @@ -23,8 +23,14 @@ function genValuePartial_fromObject(gen, field, fieldIndex, prop) { if (field.resolvedType instanceof Enum) { gen ("switch(d%s){", prop); for (var values = field.resolvedType.values, keys = Object.keys(values), i = 0; i < keys.length; ++i) { - if (field.repeated && values[keys[i]] === field.typeDefault) gen - ("default:"); + // enum unknown values passthrough + if (values[keys[i]] === field.typeDefault) { gen + ("default:") + ("if(typeof(d%s)===\"number\"){m%s=d%s;break}", prop, prop, prop); + if (!field.repeated) gen // fallback to default value only for + // arrays, to avoid leaving holes. + ("break"); // for non-repeated fields, just ignore + } gen ("case%j:", keys[i]) ("case %i:", values[keys[i]]) @@ -156,7 +162,7 @@ function genValuePartial_toObject(gen, field, fieldIndex, prop) { /* eslint-disable no-unexpected-multiline, block-scoped-var, no-redeclare */ if (field.resolvedType) { if (field.resolvedType instanceof Enum) gen - ("d%s=o.enums===String?types[%i].values[m%s]:m%s", prop, fieldIndex, prop, prop); + ("d%s=o.enums===String?(types[%i].values[m%s]===undefined?m%s:types[%i].values[m%s]):m%s", prop, fieldIndex, prop, prop, fieldIndex, prop, prop); else gen ("d%s=types[%i].toObject(m%s,o)", prop, fieldIndex, prop); } else { diff --git a/tests/api_converters.js b/tests/api_converters.js index ccfd68be6..0ad9010d1 100644 --- a/tests/api_converters.js +++ b/tests/api_converters.js @@ -103,7 +103,7 @@ tape.test("converters", function(test) { bytesVal: buf, bytesRepeated: [buf, buf], enumVal: 2, - enumRepeated: [1, 2], + enumRepeated: [1, 100, 2], int64Map: { a: protobuf.util.Long.fromNumber(2), b: protobuf.util.Long.fromNumber(3) @@ -127,6 +127,7 @@ tape.test("converters", function(test) { test.ok(Buffer.isBuffer(Message.toObject(msg, { bytes: Buffer }).bytesVal), "bytes to buffers"); test.equal(Message.toObject(msg, { enums: String }).enumVal, "TWO", "enums to strings"); + test.equal(Message.toObject(msg, { enums: String }).enumRepeated[1], 100, "enums to strings does not change unknown values"); test.end(); }); @@ -157,7 +158,7 @@ tape.test("converters", function(test) { bytesVal: "MTEx", bytesRepeated: ["MTEx", [49, 49, 49]], enumVal: "ONE", - enumRepeated: [2, "TWO"], + enumRepeated: [2, "TWO", 100], int64Map: { a: 2, b: "3" @@ -176,7 +177,7 @@ tape.test("converters", function(test) { test.same(msg.bytesVal, buf, "should set bytesVal from a base64 string"); test.same(msg.bytesRepeated, [ buf, buf ], "should set bytesRepeated from a base64 string and a plain array"); test.equal(msg.enumVal, 1, "should set enumVal from a string"); - test.same(msg.enumRepeated, [ 2, 2 ], "should set enumRepeated from a number and a string"); + test.same(msg.enumRepeated, [ 2, 2, 100 ], "should set enumRepeated from a number and a string and preserve unknown value"); test.same(msg.int64Map, { a: { low: 2, high: 0, unsigned: false }, b: { low: 3, high: 0, unsigned: false } }, "should set int64Map from a number and a string"); test.end();