Skip to content

Commit 90afe44

Browse files
fix: fromObject should not initialize oneof members (#1597)
* test: adding test for pbjs static code generation * fix: fromObject should not initialize oneof members
1 parent 6c4d307 commit 90afe44

File tree

4 files changed

+96
-5
lines changed

4 files changed

+96
-5
lines changed

cli/targets/static.js

+3-5
Original file line numberDiff line numberDiff line change
@@ -394,8 +394,7 @@ function buildType(ref, type) {
394394
if (config.comments) {
395395
push("");
396396
var jsType = toJsType(field);
397-
if (field.optional && !field.map && !field.repeated && field.resolvedType instanceof Type ||
398-
field.options && field.options.proto3_optional)
397+
if (field.optional && !field.map && !field.repeated && field.resolvedType instanceof Type || field.partOf)
399398
jsType = jsType + "|null|undefined";
400399
pushComment([
401400
field.comment || type.name + " " + field.name + ".",
@@ -411,9 +410,8 @@ function buildType(ref, type) {
411410
push(escapeName(type.name) + ".prototype" + prop + " = $util.emptyArray;"); // overwritten in constructor
412411
else if (field.map)
413412
push(escapeName(type.name) + ".prototype" + prop + " = $util.emptyObject;"); // overwritten in constructor
414-
else if (field.options && field.options.proto3_optional) {
415-
push(escapeName(type.name) + ".prototype" + prop + " = null;"); // do not set default value for proto3 optional fields
416-
}
413+
else if (field.partOf)
414+
push(escapeName(type.name) + ".prototype" + prop + " = null;"); // do not set default value for oneof members
417415
else if (field.long)
418416
push(escapeName(type.name) + ".prototype" + prop + " = $util.Long ? $util.Long.fromBits("
419417
+ JSON.stringify(field.typeDefault.low) + ","

package.json

+4
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,10 @@
5656
"browserify-wrap": "^1.0.2",
5757
"bundle-collapser": "^1.3.0",
5858
"chalk": "^4.0.0",
59+
"escodegen": "^1.13.0",
5960
"eslint": "^7.0.0",
61+
"espree": "^7.1.0",
62+
"estraverse": "^5.1.0",
6063
"gh-pages": "^3.0.0",
6164
"git-raw-commits": "^2.0.3",
6265
"git-semver-tags": "^4.0.0",
@@ -74,6 +77,7 @@
7477
"tape": "^5.0.0",
7578
"tslint": "^6.0.0",
7679
"typescript": "^3.7.5",
80+
"uglify-js": "^3.7.7",
7781
"vinyl-buffer": "^1.0.1",
7882
"vinyl-fs": "^3.0.3",
7983
"vinyl-source-stream": "^2.0.0"

tests/cli.js

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// A minimal test for pbjs tool targets.
2+
3+
var tape = require("tape");
4+
var path = require("path");
5+
var Module = require("module");
6+
var protobuf = require("..");
7+
8+
tape.test("pbjs generates static code", function(test) {
9+
// pbjs does not seem to work with Node v4, so skip this test if we're running on it
10+
if (process.versions.node.match(/^4\./)) {
11+
test.end();
12+
return;
13+
}
14+
15+
// Alter the require cache to make the cli/targets/static work since it requires "protobufjs"
16+
// and we don't want to mess with "npm link"
17+
var savedResolveFilename = Module._resolveFilename;
18+
Module._resolveFilename = function(request, parent) {
19+
if (request.startsWith("protobufjs")) {
20+
return request;
21+
}
22+
return savedResolveFilename(request, parent);
23+
};
24+
require.cache.protobufjs = require.cache[path.resolve("index.js")];
25+
26+
var staticTarget = require("../cli/targets/static");
27+
28+
var root = protobuf.loadSync("tests/data/cli/test.proto");
29+
root.resolveAll();
30+
31+
staticTarget(root, {
32+
create: true,
33+
decode: true,
34+
encode: true,
35+
convert: true,
36+
}, function(err, jsCode) {
37+
test.error(err, 'static code generation worked');
38+
39+
// jsCode is the generated code; we'll eval it
40+
// (since this is what we normally does with the code, right?)
41+
// This is a test code. Do not use this in production.
42+
var $protobuf = protobuf;
43+
eval(jsCode);
44+
45+
var OneofContainer = protobuf.roots.default.OneofContainer;
46+
var Message = protobuf.roots.default.Message;
47+
test.ok(OneofContainer, "type is loaded");
48+
test.ok(Message, "type is loaded");
49+
50+
// Check that fromObject and toObject work for plain object
51+
var obj = {
52+
messageInOneof: {
53+
value: 42,
54+
},
55+
regularField: "abc",
56+
};
57+
var obj1 = OneofContainer.toObject(OneofContainer.fromObject(obj));
58+
test.deepEqual(obj, obj1, "fromObject and toObject work for plain object");
59+
60+
// Check that dynamic fromObject and toObject work for static instance
61+
var root = protobuf.loadSync("tests/data/cli/test.proto");
62+
var OneofContainerDynamic = root.lookup("OneofContainer");
63+
var instance = new OneofContainer();
64+
instance.messageInOneof = new Message();
65+
instance.messageInOneof.value = 42;
66+
instance.regularField = "abc";
67+
var instance1 = OneofContainerDynamic.toObject(OneofContainerDynamic.fromObject(instance));
68+
test.deepEqual(instance, instance1, "fromObject and toObject work for instance of the static type");
69+
70+
test.end();
71+
});
72+
73+
// Rollback all the require() related mess we made
74+
delete require.cache.protobufjs;
75+
Module._resolveFilename = savedResolveFilename;
76+
});

tests/data/cli/test.proto

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
syntax = "proto3";
2+
3+
message Message {
4+
int32 value = 1;
5+
}
6+
7+
message OneofContainer {
8+
oneof some_oneof {
9+
string string_in_oneof = 1;
10+
Message message_in_oneof = 2;
11+
}
12+
string regular_field = 3;
13+
}

0 commit comments

Comments
 (0)