Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 14 additions & 16 deletions src/object.js
Original file line number Diff line number Diff line change
Expand Up @@ -232,23 +232,21 @@ ReflectionObject.prototype._resolveFeatures = function _resolveFeatures(edition)
throw new Error("Unknown edition: " + edition);
}
this._features = Object.assign(defaults, protoFeatures || {});
this._featuresResolved = true;
return;
}

// fields in Oneofs aren't actually children of them, so we have to
// special-case it
/* istanbul ignore else */
if (this.partOf instanceof OneOf) {
var lexicalParentFeaturesCopy = Object.assign({}, this.partOf._features);
this._features = Object.assign(lexicalParentFeaturesCopy, protoFeatures || {});
} else if (this.declaringField) {
// Skip feature resolution of sister fields.
} else if (this.parent) {
var parentFeaturesCopy = Object.assign({}, this.parent._features);
this._features = Object.assign(parentFeaturesCopy, protoFeatures || {});
} else {
throw new Error("Unable to find a parent for " + this.fullName);
// fields in Oneofs aren't actually children of them, so we have to
// special-case it
/* istanbul ignore else */
if (this.partOf instanceof OneOf) {
var lexicalParentFeaturesCopy = Object.assign({}, this.partOf._features);
this._features = Object.assign(lexicalParentFeaturesCopy, protoFeatures || {});
} else if (this.declaringField) {
// Skip feature resolution of sister fields.
} else if (this.parent) {
var parentFeaturesCopy = Object.assign({}, this.parent._features);
this._features = Object.assign(parentFeaturesCopy, protoFeatures || {});
} else {
throw new Error("Unable to find a parent for " + this.fullName);
}
}
if (this.extensionField) {
// Sister fields should have the same features as their extensions.
Expand Down
10 changes: 7 additions & 3 deletions src/parse.js
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ function parse(source, root, options) {
function parseField(parent, rule, extend) {
var type = next();
if (type === "group") {
parseGroup(parent, rule);
parseGroup(parent, rule, extend);
return;
}
// Type names can consume multiple tokens, in multiple variants:
Expand Down Expand Up @@ -504,7 +504,7 @@ function parse(source, root, options) {
}
}

function parseGroup(parent, rule) {
function parseGroup(parent, rule, extend) {
if (edition >= 2023) {
throw illegal("group");
}
Expand All @@ -521,7 +521,7 @@ function parse(source, root, options) {
var id = parseId(next());
var type = new Type(name);
type.group = true;
var field = new Field(fieldName, id, name, rule);
var field = new Field(fieldName, id, name, rule, extend);
field.filename = parse.filename;
ifBlock(type, function parseGroup_block(token) {
switch (token) {
Expand Down Expand Up @@ -584,6 +584,10 @@ function parse(source, root, options) {
});
parent.add(type)
.add(field);
if (parent === ptr) {
topLevelObjects.push(type);
topLevelObjects.push(field);
}
}

function parseMapField(parent) {
Expand Down
30 changes: 30 additions & 0 deletions tests/comp_groups.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ var protoRepeated = "message Test {\
};\
}";

var protoExtension = "syntax = \"proto2\";\
message Message {\
extensions 100 to max;\
}\
extend Message {\
optional group GroupField = 100 {\
optional uint32 a = 101;\
}\
}";

tape.test("legacy groups", function(test) {
var root = protobuf.parse(protoRequired).root.resolveAll();

Expand Down Expand Up @@ -159,3 +169,23 @@ tape.test("delimited encoding", function(test) {

test.end();
});

tape.test("extension groups", function(test) {
var root = protobuf.parse(protoExtension).root.resolveAll();

var Message = root.lookupType("Message");
var GroupField = root.get("groupField");
var ExtensionField = Message.get(GroupField.fullName);
var msg = {};
msg[GroupField.fullName] = {
a: 111
};

test.equal(ExtensionField.declaringField, GroupField, "should add the sister field to the extended type");
test.equal(ExtensionField.delimited, true, "should use delimited encoding on the sister field");

var buf = Message.encode(msg).finish();
test.same(Array.prototype.slice.call(buf), [ 163, 6, 168, 6, 111, 164, 6 ], "should encode as a group");
test.same(Message.decode(buf), msg, "and decode back the original message");
test.end();
});