Description
protobuf.js version: 6.8.6
I have several places in my code where I'd like to clone a protobuf object and make changes to the clone that don't affect the original. I've tried several methods but haven't been able to find one that works and is efficient.
Here are some examples:
test.proto
package test;
syntax = "proto3";
message Inner {
string id = 1;
}
message Test {
string id = 1;
repeated Inner inner = 2;
}
$ pbjs -t static-module -w commonjs -o compiled.js test.proto
test.js:
var clone = require('clone');
var proto = require('./compiled');
var a = proto.test.Test.create();
// Clone method goes here.
b.inner.push(proto.test.Inner.create());
if (a.inner.length != 0) {
throw new Error();
}
First, I tried using the clone
package:
var b = clone(a);
This causes some kind of problem with the prototype of the object.
test.js:11
b.inner.push(proto.test.Inner.create());
^
TypeError: Cannot add property 0, object is not extensible
at Array.push (<anonymous>)
at Object.<anonymous> (/usr/local/google/home/fjord/m/protoissue/test.js:11:9)
at Module._compile (module.js:569:30)
at Object.Module._extensions..js (module.js:580:10)
at Module.load (module.js:503:32)
at tryModuleLoad (module.js:466:12)
at Function.Module._load (module.js:458:3)
at Function.Module.runMain (module.js:605:10)
at startup (bootstrap_node.js:158:16)
at bootstrap_node.js:575:3
Then, I tried just passing the first object to create
:
var b = proto.test.Test.create(a);
This doesn't produce a deep clone:
test.js:13
throw new Error();
^
Then, I tired to/from Object:
var b = proto.test.Test.fromObject(proto.test.Test.toObject(a));
This works, but toObject
only supports an actual Test
proto object, and we want our API to support users supplying any object that matches ITest
.
This is the approach we ended up using:
var b = proto.test.Test.decode(proto.test.Test.encode(a).finish());
This produces an actual deep clone (guaranteed because object references clearly aren't preserved across serialization) and it works with either Test or ITest. However, this seems really heavyweight for just cloning an object.
Do you have suggestions for the best way to do this? It would be great if protobuf.js had a clone() method that was the officially supported way of cloning an object.
Thanks!