Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support extensions #666

Merged
merged 8 commits into from
Jan 18, 2024
Merged
Show file tree
Hide file tree
Changes from 4 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
2 changes: 1 addition & 1 deletion packages/protobuf-bench/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ server would usually do.

| code generator | bundle size | minified | compressed |
|---------------------|------------------------:|-----------------------:|-------------------:|
| protobuf-es | 95,543 b | 40,794 b | 10,615 b |
| protobuf-es | 95,758 b | 40,907 b | 10,634 b |
| protobuf-javascript | 394,384 b | 288,654 b | 45,122 b |
9 changes: 9 additions & 0 deletions packages/protobuf-test/extra/extensions-proto2.proto
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,15 @@ extend Proto2Extendee {
repeated uint32 unpacked_uint32_ext = 7004; // unpacked by default in proto2

optional google.protobuf.UInt32Value wrapper_ext = 8001;

optional group GroupExt = 8100 {
optional int32 a = 1;
optional int32 b = 2;
}
repeated group RepeatedGroupExt = 8101 {
optional int32 a = 1;
optional int32 b = 2;
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since groups are now ostensibly supported, let's also add a group extension, to make sure they work, too. (Maybe a repeated group extension, too?)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 added in 97b9729.


// A container for nested extensions
Expand Down
145 changes: 145 additions & 0 deletions packages/protobuf-test/src/extensions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ import {
bytes_ext_with_default,
enum_ext,
enum_ext_with_default,
GroupExt,
groupext,
message_ext,
message_ext_proto3,
packed_uint32_ext,
Expand All @@ -47,6 +49,8 @@ import {
repeated_enum_ext,
repeated_message_ext,
repeated_string_ext,
RepeatedGroupExt,
repeatedgroupext,
string_ext,
string_ext_with_default,
uint32_ext,
Expand Down Expand Up @@ -80,6 +84,11 @@ const goldenValues: ReadonlyMap<Extension<Proto2Extendee>, unknown> = new Map<
[packed_uint32_ext, [1, 2, 3]],
[unpacked_uint32_ext, [4, 5, 6]],
[wrapper_ext, 123],
[groupext, new GroupExt({ a: 123 })],
[
repeatedgroupext,
[new RepeatedGroupExt({ a: 123 }), new RepeatedGroupExt({ a: 456 })],
],
[Proto2ExtContainer_uint32_ext, 1234],
[Proto2ExtContainer_Child_uint32_ext, 12345],
]);
Expand All @@ -105,6 +114,8 @@ const goldenValuesZero: ReadonlyMap<
[packed_uint32_ext, []],
[unpacked_uint32_ext, []],
[wrapper_ext, 0],
[groupext, new GroupExt()],
[repeatedgroupext, []],
[Proto2ExtContainer_uint32_ext, 0],
[Proto2ExtContainer_Child_uint32_ext, 0],
]);
Expand Down Expand Up @@ -161,6 +172,12 @@ describe("proto2.makeExtension()", () => {
});

describe("getExtension()", () => {
it("should throw error if extendee does not match", () => {
const msg = new User();
expect(() => getExtension(msg as Proto2Extendee, uint32_ext)).toThrow(
/^extension proto2ext.uint32_ext can only be applied to message proto2ext.Proto2Extendee$/,
);
});
describe("for scalar", () => {
it("should parse from unknown fields", () => {
const msg = new Proto2Extendee();
Expand Down Expand Up @@ -484,6 +501,117 @@ describe("getExtension()", () => {
expect(getExtension(msg, repeated_message_ext)).toStrictEqual([]);
});
});
describe("for group", () => {
function addUnknownGroupField(
message: Proto2Extendee,
fieldNo: number,
value: Message,
) {
message
.getType()
.runtime.bin.onUnknownField(
message,
fieldNo,
WireType.StartGroup,
value
.getType()
.runtime.bin.makeWriteOptions()
.writerFactory()
.raw(value.toBinary())
.tag(fieldNo, WireType.EndGroup)
.finish(),
);
}

it("should return value parsed from unknown fields", () => {
const msg = new Proto2Extendee();
addUnknownGroupField(
msg,
groupext.field.no,
new GroupExt({
a: 123,
}),
);
const value = getExtension(msg, groupext);
expect(value).toBeInstanceOf(GroupExt);
expect(value.a).toBe(123);
});
it("should return merged value parsed from multiple unknown fields", () => {
const msg = new Proto2Extendee();
addUnknownGroupField(
msg,
groupext.field.no,
new GroupExt({
a: 123,
}),
);
addUnknownGroupField(
msg,
groupext.field.no,
new GroupExt({
b: 456,
}),
);
const value = getExtension(msg, groupext);
expect(value).toBeInstanceOf(GroupExt);
expect(value.a).toBe(123);
expect(value.b).toBe(456);
});
it("should return empty group if unset", () => {
const msg = new Proto2Extendee();
const value = getExtension(msg, groupext);
expect(value).toBeInstanceOf(GroupExt);
expect(new GroupExt().equals(value)).toBeTruthy();
});
});
describe("for repeated group", () => {
function addUnknownGroupField(
message: Proto2Extendee,
fieldNo: number,
value: Message,
) {
message
.getType()
.runtime.bin.onUnknownField(
message,
fieldNo,
WireType.StartGroup,
value
.getType()
.runtime.bin.makeWriteOptions()
.writerFactory()
.raw(value.toBinary())
.tag(fieldNo, WireType.EndGroup)
.finish(),
);
}

it("should parse from unknown fields", () => {
const msg = new Proto2Extendee();
addUnknownGroupField(
msg,
repeatedgroupext.field.no,
new RepeatedGroupExt({
a: 123,
}),
);
addUnknownGroupField(
msg,
repeatedgroupext.field.no,
new RepeatedGroupExt({
a: 456,
}),
);
const arr = getExtension(msg, repeatedgroupext);
expect(arr.length).toBe(2);
expect(arr[0].a).toBe(123);
expect(arr[1].a).toBe(456);
});
it("should return zero value if unset", () => {
const msg = new Proto2Extendee();
expect(getExtension(msg, repeatedgroupext)).toStrictEqual([]);
});
});
});

describe("hasExtension()", () => {
Expand Down Expand Up @@ -556,9 +684,21 @@ describe("clearExtension()", () => {
clearExtension(msg, uint32_ext);
expect(listUnknownFieldNumbers(msg)).toStrictEqual([500, 1500]);
});
it("should throw error if extendee does not match", () => {
const msg = new User();
expect(() => clearExtension(msg as Proto2Extendee, uint32_ext)).toThrow(
/^extension proto2ext.uint32_ext can only be applied to message proto2ext.Proto2Extendee$/,
);
});
});

describe("setExtension()", () => {
it("should throw error if extendee does not match", () => {
const msg = new User();
expect(() => setExtension(msg as Proto2Extendee, uint32_ext, 123)).toThrow(
/^extension proto2ext.uint32_ext can only be applied to message proto2ext.Proto2Extendee$/,
);
});
for (const [ext, val] of Array.from(goldenValues.entries())) {
it(`should set ${ext.typeName} as expected`, () => {
const msg = new Proto2Extendee();
Expand Down Expand Up @@ -696,6 +836,8 @@ describe("extensions with JSON", () => {
packed_uint32_ext,
unpacked_uint32_ext,
wrapper_ext,
groupext,
repeatedgroupext,
Proto2ExtContainer_uint32_ext,
Proto2ExtContainer_Child_uint32_ext,
);
Expand Down Expand Up @@ -729,6 +871,8 @@ describe("extensions with JSON", () => {
"[proto2ext.repeated_string_ext]": ["a", "b", "c"],
"[proto2ext.unpacked_uint32_ext]": [4, 5, 6],
"[proto2ext.wrapper_ext]": 123,
"[proto2ext.groupext]": { a: 123 },
"[proto2ext.repeatedgroupext]": [{ a: 123 }, { a: 456 }],
"[proto2ext.Proto2ExtContainer.uint32_ext]": 1234,
"[proto2ext.Proto2ExtContainer.Child.uint32_ext]": 12345,
};
Expand All @@ -746,6 +890,7 @@ describe("extensions with JSON", () => {
"[proto2ext.message_ext]": {},
"[proto2ext.message_ext_proto3]": {},
"[proto2ext.wrapper_ext]": 0,
"[proto2ext.groupext]": {},
"[proto2ext.Proto2ExtContainer.uint32_ext]": 0,
"[proto2ext.Proto2ExtContainer.Child.uint32_ext]": 0,
};
Expand Down
68 changes: 68 additions & 0 deletions packages/protobuf-test/src/gen/js/extra/extensions-proto2_pb.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 40 additions & 0 deletions packages/protobuf-test/src/gen/js/extra/extensions-proto2_pb.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading