@bufbuild/protobuf 1.6.0 → 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. package/dist/cjs/binary-encoding.js +2 -3
  2. package/dist/cjs/binary-format.d.ts +17 -0
  3. package/dist/cjs/binary-format.js +1 -1
  4. package/dist/cjs/codegen-info.d.ts +4 -4
  5. package/dist/cjs/codegen-info.js +2 -1
  6. package/dist/cjs/create-descriptor-set.d.ts +7 -1
  7. package/dist/cjs/create-descriptor-set.js +56 -50
  8. package/dist/cjs/create-registry-from-desc.d.ts +2 -2
  9. package/dist/cjs/create-registry-from-desc.js +53 -9
  10. package/dist/cjs/create-registry.d.ts +3 -2
  11. package/dist/cjs/create-registry.js +56 -37
  12. package/dist/cjs/descriptor-set.js +1 -1
  13. package/dist/cjs/enum.js +1 -1
  14. package/dist/cjs/extension-accessor.d.ts +35 -0
  15. package/dist/cjs/extension-accessor.js +108 -0
  16. package/dist/cjs/extension.d.ts +24 -0
  17. package/dist/cjs/extension.js +15 -0
  18. package/dist/cjs/field-list.js +1 -1
  19. package/dist/cjs/field.js +1 -1
  20. package/dist/cjs/google/protobuf/any_pb.js +1 -1
  21. package/dist/cjs/google/protobuf/api_pb.js +1 -1
  22. package/dist/cjs/google/protobuf/compiler/plugin_pb.js +1 -1
  23. package/dist/cjs/google/protobuf/descriptor_pb.js +2 -2
  24. package/dist/cjs/google/protobuf/duration_pb.js +1 -1
  25. package/dist/cjs/google/protobuf/empty_pb.js +1 -1
  26. package/dist/cjs/google/protobuf/field_mask_pb.js +1 -1
  27. package/dist/cjs/google/protobuf/source_context_pb.js +1 -1
  28. package/dist/cjs/google/protobuf/struct_pb.js +2 -2
  29. package/dist/cjs/google/protobuf/timestamp_pb.js +1 -1
  30. package/dist/cjs/google/protobuf/type_pb.js +2 -2
  31. package/dist/cjs/google/protobuf/wrappers_pb.js +1 -1
  32. package/dist/cjs/index.d.ts +3 -1
  33. package/dist/cjs/index.js +7 -2
  34. package/dist/cjs/json-format.d.ts +5 -5
  35. package/dist/cjs/json-format.js +1 -1
  36. package/dist/cjs/message-type.js +1 -1
  37. package/dist/cjs/message.js +1 -1
  38. package/dist/cjs/private/assert.js +1 -1
  39. package/dist/cjs/private/binary-format-common.d.ts +2 -3
  40. package/dist/cjs/private/binary-format-common.js +80 -78
  41. package/dist/cjs/private/binary-format-proto2.js +59 -64
  42. package/dist/cjs/private/binary-format-proto3.js +44 -40
  43. package/dist/cjs/private/enum.js +1 -1
  44. package/dist/cjs/private/extensions.d.ts +34 -0
  45. package/dist/cjs/private/extensions.js +86 -0
  46. package/dist/cjs/private/feature-set.d.ts +6 -8
  47. package/dist/cjs/private/feature-set.js +41 -42
  48. package/dist/cjs/private/field-list.js +1 -1
  49. package/dist/cjs/private/field-wrapper.d.ts +2 -2
  50. package/dist/cjs/private/field-wrapper.js +1 -1
  51. package/dist/cjs/private/field.js +1 -1
  52. package/dist/cjs/private/json-format-common.d.ts +3 -3
  53. package/dist/cjs/private/json-format-common.js +228 -173
  54. package/dist/cjs/private/json-format-proto2.js +3 -2
  55. package/dist/cjs/private/json-format-proto3.js +8 -6
  56. package/dist/cjs/private/message-type.js +1 -1
  57. package/dist/cjs/private/names.d.ts +2 -2
  58. package/dist/cjs/private/names.js +3 -2
  59. package/dist/cjs/private/options-map.js +1 -1
  60. package/dist/cjs/private/proto-runtime.d.ts +6 -0
  61. package/dist/cjs/private/proto-runtime.js +5 -1
  62. package/dist/cjs/private/reify-wkt.js +1 -1
  63. package/dist/cjs/private/scalars.js +1 -1
  64. package/dist/cjs/private/text-format.js +1 -1
  65. package/dist/cjs/private/util-common.js +1 -1
  66. package/dist/cjs/private/util.js +1 -1
  67. package/dist/cjs/proto-base64.js +1 -1
  68. package/dist/cjs/proto-delimited.js +1 -1
  69. package/dist/cjs/proto-double.js +1 -1
  70. package/dist/cjs/proto-int64.js +1 -1
  71. package/dist/cjs/proto2.js +1 -1
  72. package/dist/cjs/proto3.js +1 -1
  73. package/dist/cjs/service-type.js +1 -1
  74. package/dist/cjs/to-plain-message.js +1 -1
  75. package/dist/cjs/type-registry.d.ts +14 -0
  76. package/dist/cjs/type-registry.js +1 -1
  77. package/dist/esm/binary-encoding.js +2 -3
  78. package/dist/esm/binary-format.d.ts +17 -0
  79. package/dist/esm/binary-format.js +1 -1
  80. package/dist/esm/codegen-info.d.ts +4 -4
  81. package/dist/esm/codegen-info.js +2 -1
  82. package/dist/esm/create-descriptor-set.d.ts +7 -1
  83. package/dist/esm/create-descriptor-set.js +57 -51
  84. package/dist/esm/create-registry-from-desc.d.ts +2 -2
  85. package/dist/esm/create-registry-from-desc.js +53 -9
  86. package/dist/esm/create-registry.d.ts +3 -2
  87. package/dist/esm/create-registry.js +56 -37
  88. package/dist/esm/descriptor-set.js +1 -1
  89. package/dist/esm/enum.js +1 -1
  90. package/dist/esm/extension-accessor.d.ts +35 -0
  91. package/dist/esm/extension-accessor.js +101 -0
  92. package/dist/esm/extension.d.ts +24 -0
  93. package/dist/esm/extension.js +14 -0
  94. package/dist/esm/field-list.js +1 -1
  95. package/dist/esm/field.js +1 -1
  96. package/dist/esm/google/protobuf/any_pb.js +1 -1
  97. package/dist/esm/google/protobuf/api_pb.js +1 -1
  98. package/dist/esm/google/protobuf/compiler/plugin_pb.js +1 -1
  99. package/dist/esm/google/protobuf/descriptor_pb.js +2 -2
  100. package/dist/esm/google/protobuf/duration_pb.js +1 -1
  101. package/dist/esm/google/protobuf/empty_pb.js +1 -1
  102. package/dist/esm/google/protobuf/field_mask_pb.js +1 -1
  103. package/dist/esm/google/protobuf/source_context_pb.js +1 -1
  104. package/dist/esm/google/protobuf/struct_pb.js +2 -2
  105. package/dist/esm/google/protobuf/timestamp_pb.js +1 -1
  106. package/dist/esm/google/protobuf/type_pb.js +2 -2
  107. package/dist/esm/google/protobuf/wrappers_pb.js +1 -1
  108. package/dist/esm/index.d.ts +3 -1
  109. package/dist/esm/index.js +2 -1
  110. package/dist/esm/json-format.d.ts +5 -5
  111. package/dist/esm/json-format.js +1 -1
  112. package/dist/esm/message-type.js +1 -1
  113. package/dist/esm/message.js +1 -1
  114. package/dist/esm/private/assert.js +1 -1
  115. package/dist/esm/private/binary-format-common.d.ts +2 -3
  116. package/dist/esm/private/binary-format-common.js +80 -77
  117. package/dist/esm/private/binary-format-proto2.js +59 -64
  118. package/dist/esm/private/binary-format-proto3.js +44 -40
  119. package/dist/esm/private/enum.js +1 -1
  120. package/dist/esm/private/extensions.d.ts +34 -0
  121. package/dist/esm/private/extensions.js +81 -0
  122. package/dist/esm/private/feature-set.d.ts +6 -8
  123. package/dist/esm/private/feature-set.js +40 -41
  124. package/dist/esm/private/field-list.js +1 -1
  125. package/dist/esm/private/field-wrapper.d.ts +2 -2
  126. package/dist/esm/private/field-wrapper.js +1 -1
  127. package/dist/esm/private/field.js +1 -1
  128. package/dist/esm/private/json-format-common.d.ts +3 -3
  129. package/dist/esm/private/json-format-common.js +228 -173
  130. package/dist/esm/private/json-format-proto2.js +3 -2
  131. package/dist/esm/private/json-format-proto3.js +8 -6
  132. package/dist/esm/private/message-type.js +1 -1
  133. package/dist/esm/private/names.d.ts +2 -2
  134. package/dist/esm/private/names.js +3 -2
  135. package/dist/esm/private/options-map.js +1 -1
  136. package/dist/esm/private/proto-runtime.d.ts +6 -0
  137. package/dist/esm/private/proto-runtime.js +5 -1
  138. package/dist/esm/private/reify-wkt.js +1 -1
  139. package/dist/esm/private/scalars.js +1 -1
  140. package/dist/esm/private/text-format.js +1 -1
  141. package/dist/esm/private/util-common.js +1 -1
  142. package/dist/esm/private/util.js +1 -1
  143. package/dist/esm/proto-base64.js +1 -1
  144. package/dist/esm/proto-delimited.js +1 -1
  145. package/dist/esm/proto-double.js +1 -1
  146. package/dist/esm/proto-int64.js +1 -1
  147. package/dist/esm/proto2.js +1 -1
  148. package/dist/esm/proto3.js +1 -1
  149. package/dist/esm/service-type.js +1 -1
  150. package/dist/esm/to-plain-message.js +1 -1
  151. package/dist/esm/type-registry.d.ts +14 -0
  152. package/dist/esm/type-registry.js +1 -1
  153. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- // Copyright 2021-2023 Buf Technologies, Inc.
2
+ // Copyright 2021-2024 Buf Technologies, Inc.
3
3
  //
4
4
  // Licensed under the Apache License, Version 2.0 (the "License");
5
5
  // you may not use this file except in compliance with the License.
@@ -19,6 +19,8 @@ const field_js_1 = require("../field.js");
19
19
  const assert_js_1 = require("./assert.js");
20
20
  const proto_int64_js_1 = require("../proto-int64.js");
21
21
  const proto_base64_js_1 = require("../proto-base64.js");
22
+ const extensions_js_1 = require("./extensions.js");
23
+ const extension_accessor_js_1 = require("../extension-accessor.js");
22
24
  /* eslint-disable no-case-declarations, @typescript-eslint/restrict-plus-operands,@typescript-eslint/no-explicit-any,@typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-argument */
23
25
  // Default options for parsing JSON.
24
26
  const jsonReadDefaults = {
@@ -37,171 +39,52 @@ function makeReadOptions(options) {
37
39
  function makeWriteOptions(options) {
38
40
  return options ? Object.assign(Object.assign({}, jsonWriteDefaults), options) : jsonWriteDefaults;
39
41
  }
40
- function makeJsonFormatCommon(makeWriteField) {
42
+ function makeJsonFormatCommon(nullAsZeroValue, makeWriteField) {
41
43
  const writeField = makeWriteField(writeEnum, writeScalar);
42
44
  return {
43
45
  makeReadOptions,
44
46
  makeWriteOptions,
45
47
  readMessage(type, json, options, message) {
46
48
  if (json == null || Array.isArray(json) || typeof json != "object") {
47
- throw new Error(`cannot decode message ${type.typeName} from JSON: ${this.debug(json)}`);
49
+ throw new Error(`cannot decode message ${type.typeName} from JSON: ${debugJsonValue(json)}`);
48
50
  }
49
51
  message = message !== null && message !== void 0 ? message : new type();
50
- const oneofSeen = {};
52
+ const oneofSeen = new Map();
53
+ const registry = options.typeRegistry;
51
54
  for (const [jsonKey, jsonValue] of Object.entries(json)) {
52
55
  const field = type.fields.findJsonName(jsonKey);
53
- if (!field) {
54
- if (!options.ignoreUnknownFields) {
55
- throw new Error(`cannot decode message ${type.typeName} from JSON: key "${jsonKey}" is unknown`);
56
- }
57
- continue;
58
- }
59
- let localName = field.localName;
60
- let target = message;
61
- if (field.oneof) {
62
- if (jsonValue === null && field.kind == "scalar") {
63
- // see conformance test Required.Proto3.JsonInput.OneofFieldNull{First,Second}
64
- continue;
65
- }
66
- const seen = oneofSeen[field.oneof.localName];
67
- if (seen) {
68
- throw new Error(`cannot decode message ${type.typeName} from JSON: multiple keys for oneof "${field.oneof.name}" present: "${seen}", "${jsonKey}"`);
69
- }
70
- oneofSeen[field.oneof.localName] = jsonKey;
71
- target = target[field.oneof.localName] = { case: localName };
72
- localName = "value";
73
- }
74
- if (field.repeated) {
75
- if (jsonValue === null) {
76
- continue;
77
- }
78
- if (!Array.isArray(jsonValue)) {
79
- throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: ${this.debug(jsonValue)}`);
80
- }
81
- const targetArray = target[localName];
82
- for (const jsonItem of jsonValue) {
83
- if (jsonItem === null) {
84
- throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: ${this.debug(jsonItem)}`);
56
+ if (field) {
57
+ if (field.oneof) {
58
+ if (jsonValue === null && field.kind == "scalar") {
59
+ // see conformance test Required.Proto3.JsonInput.OneofFieldNull{First,Second}
60
+ continue;
85
61
  }
86
- let val;
87
- // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check -- "map" is invalid for repeated fields
88
- switch (field.kind) {
89
- case "message":
90
- val = field.T.fromJson(jsonItem, options);
91
- break;
92
- case "enum":
93
- val = readEnum(field.T, jsonItem, options.ignoreUnknownFields);
94
- if (val === undefined)
95
- continue;
96
- break;
97
- case "scalar":
98
- try {
99
- val = readScalar(field.T, jsonItem, field.L);
100
- }
101
- catch (e) {
102
- let m = `cannot decode field ${type.typeName}.${field.name} from JSON: ${this.debug(jsonItem)}`;
103
- if (e instanceof Error && e.message.length > 0) {
104
- m += `: ${e.message}`;
105
- }
106
- throw new Error(m);
107
- }
108
- break;
62
+ const seen = oneofSeen.get(field.oneof);
63
+ if (seen !== undefined) {
64
+ throw new Error(`cannot decode message ${type.typeName} from JSON: multiple keys for oneof "${field.oneof.name}" present: "${seen}", "${jsonKey}"`);
109
65
  }
110
- targetArray.push(val);
66
+ oneofSeen.set(field.oneof, jsonKey);
111
67
  }
68
+ readField(message, jsonValue, field, options, type, nullAsZeroValue);
112
69
  }
113
- else if (field.kind == "map") {
114
- if (jsonValue === null) {
115
- continue;
116
- }
117
- if (Array.isArray(jsonValue) || typeof jsonValue != "object") {
118
- throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: ${this.debug(jsonValue)}`);
119
- }
120
- const targetMap = target[localName];
121
- for (const [jsonMapKey, jsonMapValue] of Object.entries(jsonValue)) {
122
- if (jsonMapValue === null) {
123
- throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: map value null`);
124
- }
125
- let val;
126
- switch (field.V.kind) {
127
- case "message":
128
- val = field.V.T.fromJson(jsonMapValue, options);
129
- break;
130
- case "enum":
131
- val = readEnum(field.V.T, jsonMapValue, options.ignoreUnknownFields);
132
- if (val === undefined)
133
- continue;
134
- break;
135
- case "scalar":
136
- try {
137
- val = readScalar(field.V.T, jsonMapValue, field_js_1.LongType.BIGINT);
138
- }
139
- catch (e) {
140
- let m = `cannot decode map value for field ${type.typeName}.${field.name} from JSON: ${this.debug(jsonValue)}`;
141
- if (e instanceof Error && e.message.length > 0) {
142
- m += `: ${e.message}`;
143
- }
144
- throw new Error(m);
145
- }
146
- break;
147
- }
148
- try {
149
- targetMap[readScalar(field.K, field.K == field_js_1.ScalarType.BOOL
150
- ? jsonMapKey == "true"
151
- ? true
152
- : jsonMapKey == "false"
153
- ? false
154
- : jsonMapKey
155
- : jsonMapKey, field_js_1.LongType.BIGINT).toString()] = val;
156
- }
157
- catch (e) {
158
- let m = `cannot decode map key for field ${type.typeName}.${field.name} from JSON: ${this.debug(jsonValue)}`;
159
- if (e instanceof Error && e.message.length > 0) {
160
- m += `: ${e.message}`;
161
- }
162
- throw new Error(m);
70
+ else {
71
+ let found = false;
72
+ if ((registry === null || registry === void 0 ? void 0 : registry.findExtension) &&
73
+ jsonKey.startsWith("[") &&
74
+ jsonKey.endsWith("]")) {
75
+ const ext = registry.findExtension(jsonKey.substring(1, jsonKey.length - 1));
76
+ if (ext && ext.extendee.typeName == type.typeName) {
77
+ found = true;
78
+ const [container, get] = (0, extensions_js_1.createExtensionContainer)(ext);
79
+ readField(container, jsonValue, ext.field, options, ext, true);
80
+ // We pass on the options as BinaryReadOptions/BinaryWriteOptions,
81
+ // so that users can bring their own binary reader and writer factories
82
+ // if necessary.
83
+ (0, extension_accessor_js_1.setExtension)(message, ext, get(), options);
163
84
  }
164
85
  }
165
- }
166
- else {
167
- switch (field.kind) {
168
- case "message":
169
- const messageType = field.T;
170
- if (jsonValue === null &&
171
- messageType.typeName != "google.protobuf.Value") {
172
- if (field.oneof) {
173
- throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: null is invalid for oneof field "${jsonKey}"`);
174
- }
175
- continue;
176
- }
177
- if (target[localName] instanceof message_js_1.Message) {
178
- target[localName].fromJson(jsonValue, options);
179
- }
180
- else {
181
- target[localName] = messageType.fromJson(jsonValue, options);
182
- if (messageType.fieldWrapper && !field.oneof) {
183
- target[localName] = messageType.fieldWrapper.unwrapField(target[localName]);
184
- }
185
- }
186
- break;
187
- case "enum":
188
- const enumValue = readEnum(field.T, jsonValue, options.ignoreUnknownFields);
189
- if (enumValue !== undefined) {
190
- target[localName] = enumValue;
191
- }
192
- break;
193
- case "scalar":
194
- try {
195
- target[localName] = readScalar(field.T, jsonValue, field.L);
196
- }
197
- catch (e) {
198
- let m = `cannot decode field ${type.typeName}.${field.name} from JSON: ${this.debug(jsonValue)}`;
199
- if (e instanceof Error && e.message.length > 0) {
200
- m += `: ${e.message}`;
201
- }
202
- throw new Error(m);
203
- }
204
- break;
86
+ if (!found && !options.ignoreUnknownFields) {
87
+ throw new Error(`cannot decode message ${type.typeName} from JSON: key "${jsonKey}" is unknown`);
205
88
  }
206
89
  }
207
90
  }
@@ -234,6 +117,21 @@ function makeJsonFormatCommon(makeWriteField) {
234
117
  jsonValue;
235
118
  }
236
119
  }
120
+ const registry = options.typeRegistry;
121
+ if (registry === null || registry === void 0 ? void 0 : registry.findExtensionFor) {
122
+ for (const uf of type.runtime.bin.listUnknownFields(message)) {
123
+ const ext = registry.findExtensionFor(type.typeName, uf.no);
124
+ if (ext && (0, extension_accessor_js_1.hasExtension)(message, ext)) {
125
+ // We pass on the options as BinaryReadOptions, so that users can bring their own
126
+ // binary reader factory if necessary.
127
+ const value = (0, extension_accessor_js_1.getExtension)(message, ext, options);
128
+ const jsonValue = writeField(ext.field, value, options);
129
+ if (jsonValue !== undefined) {
130
+ json[ext.field.jsonName] = jsonValue;
131
+ }
132
+ }
133
+ }
134
+ }
237
135
  }
238
136
  catch (e) {
239
137
  const m = field
@@ -244,7 +142,7 @@ function makeJsonFormatCommon(makeWriteField) {
244
142
  }
245
143
  return json;
246
144
  },
247
- readScalar,
145
+ readScalar: (type, json, longType) => readScalar(type, json, longType, nullAsZeroValue), // eslint-disable-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-return
248
146
  writeScalar,
249
147
  debug: debugJsonValue,
250
148
  };
@@ -263,9 +161,162 @@ function debugJsonValue(json) {
263
161
  return String(json);
264
162
  }
265
163
  }
164
+ // Read a JSON value for a field.
165
+ // The "type" argument is only used to provide context in errors.
166
+ // The argument "nullAsZeroValue" applies to singular fields (not repeated, map,
167
+ // or oneof). If the argument is `true`, JSON null is parsed as the fields
168
+ // zero-value. If the argument is false, JSON null sets the field to `undefined`.
169
+ function readField(target, // eslint-disable-line @typescript-eslint/no-explicit-any -- `any` is the best choice for dynamic access
170
+ jsonValue, field, options, type, nullAsZeroValue) {
171
+ let localName = field.localName;
172
+ if (field.oneof) {
173
+ if (jsonValue === null && field.kind == "scalar") {
174
+ // see conformance test Required.Proto3.JsonInput.OneofFieldNull{First,Second}
175
+ return;
176
+ }
177
+ target = target[field.oneof.localName] = { case: localName };
178
+ localName = "value";
179
+ }
180
+ if (field.repeated) {
181
+ if (jsonValue === null) {
182
+ return;
183
+ }
184
+ if (!Array.isArray(jsonValue)) {
185
+ throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonValue)}`);
186
+ }
187
+ const targetArray = target[localName];
188
+ for (const jsonItem of jsonValue) {
189
+ if (jsonItem === null) {
190
+ throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonItem)}`);
191
+ }
192
+ let val;
193
+ // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check -- "map" is invalid for repeated fields
194
+ switch (field.kind) {
195
+ case "message":
196
+ val = field.T.fromJson(jsonItem, options);
197
+ break;
198
+ case "enum":
199
+ val = readEnum(field.T, jsonItem, options.ignoreUnknownFields, true);
200
+ if (val === undefined)
201
+ continue;
202
+ break;
203
+ case "scalar":
204
+ try {
205
+ val = readScalar(field.T, jsonItem, field.L, true);
206
+ }
207
+ catch (e) {
208
+ let m = `cannot decode field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonItem)}`;
209
+ if (e instanceof Error && e.message.length > 0) {
210
+ m += `: ${e.message}`;
211
+ }
212
+ throw new Error(m);
213
+ }
214
+ break;
215
+ }
216
+ targetArray.push(val);
217
+ }
218
+ }
219
+ else if (field.kind == "map") {
220
+ if (jsonValue === null) {
221
+ return;
222
+ }
223
+ if (typeof jsonValue != "object" || Array.isArray(jsonValue)) {
224
+ throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonValue)}`);
225
+ }
226
+ const targetMap = target[localName];
227
+ for (const [jsonMapKey, jsonMapValue] of Object.entries(jsonValue)) {
228
+ if (jsonMapValue === null) {
229
+ throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: map value null`);
230
+ }
231
+ let val;
232
+ switch (field.V.kind) {
233
+ case "message":
234
+ val = field.V.T.fromJson(jsonMapValue, options);
235
+ break;
236
+ case "enum":
237
+ val = readEnum(field.V.T, jsonMapValue, options.ignoreUnknownFields, true);
238
+ if (val === undefined)
239
+ continue;
240
+ break;
241
+ case "scalar":
242
+ try {
243
+ val = readScalar(field.V.T, jsonMapValue, field_js_1.LongType.BIGINT, true);
244
+ }
245
+ catch (e) {
246
+ let m = `cannot decode map value for field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonValue)}`;
247
+ if (e instanceof Error && e.message.length > 0) {
248
+ m += `: ${e.message}`;
249
+ }
250
+ throw new Error(m);
251
+ }
252
+ break;
253
+ }
254
+ try {
255
+ targetMap[readScalar(field.K, field.K == field_js_1.ScalarType.BOOL
256
+ ? jsonMapKey == "true"
257
+ ? true
258
+ : jsonMapKey == "false"
259
+ ? false
260
+ : jsonMapKey
261
+ : jsonMapKey, field_js_1.LongType.BIGINT, true).toString()] = val;
262
+ }
263
+ catch (e) {
264
+ let m = `cannot decode map key for field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonValue)}`;
265
+ if (e instanceof Error && e.message.length > 0) {
266
+ m += `: ${e.message}`;
267
+ }
268
+ throw new Error(m);
269
+ }
270
+ }
271
+ }
272
+ else {
273
+ switch (field.kind) {
274
+ case "message":
275
+ const messageType = field.T;
276
+ if (jsonValue === null &&
277
+ messageType.typeName != "google.protobuf.Value") {
278
+ if (field.oneof) {
279
+ throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: null is invalid for oneof field`);
280
+ }
281
+ return;
282
+ }
283
+ if (target[localName] instanceof message_js_1.Message) {
284
+ target[localName].fromJson(jsonValue, options);
285
+ }
286
+ else {
287
+ target[localName] = messageType.fromJson(jsonValue, options);
288
+ if (messageType.fieldWrapper && !field.oneof) {
289
+ target[localName] = messageType.fieldWrapper.unwrapField(target[localName]);
290
+ }
291
+ }
292
+ break;
293
+ case "enum":
294
+ const enumValue = readEnum(field.T, jsonValue, options.ignoreUnknownFields, nullAsZeroValue);
295
+ if (enumValue !== undefined) {
296
+ target[localName] = enumValue;
297
+ }
298
+ break;
299
+ case "scalar":
300
+ try {
301
+ target[localName] = readScalar(field.T, jsonValue, field.L, nullAsZeroValue);
302
+ }
303
+ catch (e) {
304
+ let m = `cannot decode field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonValue)}`;
305
+ if (e instanceof Error && e.message.length > 0) {
306
+ m += `: ${e.message}`;
307
+ }
308
+ throw new Error(m);
309
+ }
310
+ break;
311
+ }
312
+ }
313
+ }
266
314
  // May throw an error. If the error message is non-blank, it should be shown.
267
315
  // It is up to the caller to provide context.
268
- function readScalar(type, json, longType) {
316
+ // If the argument "nullAsZeroValue" is `true`, this function returns the zero-value
317
+ // for JSON null. If the argument is `false`, this function returns `undefined`
318
+ // for JSON null.
319
+ function readScalar(type, json, longType, nullAsZeroValue) {
269
320
  // every valid case in the switch below returns, and every fall
270
321
  // through is regarded as a failure.
271
322
  switch (type) {
@@ -274,7 +325,7 @@ function readScalar(type, json, longType) {
274
325
  case field_js_1.ScalarType.DOUBLE:
275
326
  case field_js_1.ScalarType.FLOAT:
276
327
  if (json === null)
277
- return 0.0;
328
+ return nullAsZeroValue ? 0.0 : undefined;
278
329
  if (json === "NaN")
279
330
  return Number.NaN;
280
331
  if (json === "Infinity")
@@ -311,7 +362,7 @@ function readScalar(type, json, longType) {
311
362
  case field_js_1.ScalarType.SINT32:
312
363
  case field_js_1.ScalarType.UINT32:
313
364
  if (json === null)
314
- return 0;
365
+ return nullAsZeroValue ? 0 : undefined;
315
366
  let int32;
316
367
  if (typeof json == "number")
317
368
  int32 = json;
@@ -331,7 +382,7 @@ function readScalar(type, json, longType) {
331
382
  case field_js_1.ScalarType.SFIXED64:
332
383
  case field_js_1.ScalarType.SINT64:
333
384
  if (json === null)
334
- return proto_int64_js_1.protoInt64.zero;
385
+ return nullAsZeroValue ? proto_int64_js_1.protoInt64.zero : undefined;
335
386
  if (typeof json != "number" && typeof json != "string")
336
387
  break;
337
388
  const long = proto_int64_js_1.protoInt64.parse(json);
@@ -340,7 +391,7 @@ function readScalar(type, json, longType) {
340
391
  case field_js_1.ScalarType.FIXED64:
341
392
  case field_js_1.ScalarType.UINT64:
342
393
  if (json === null)
343
- return proto_int64_js_1.protoInt64.zero;
394
+ return nullAsZeroValue ? proto_int64_js_1.protoInt64.zero : undefined;
344
395
  if (typeof json != "number" && typeof json != "string")
345
396
  break;
346
397
  const uLong = proto_int64_js_1.protoInt64.uParse(json);
@@ -349,14 +400,14 @@ function readScalar(type, json, longType) {
349
400
  // bool:
350
401
  case field_js_1.ScalarType.BOOL:
351
402
  if (json === null)
352
- return false;
403
+ return nullAsZeroValue ? false : undefined;
353
404
  if (typeof json !== "boolean")
354
405
  break;
355
406
  return json;
356
407
  // string:
357
408
  case field_js_1.ScalarType.STRING:
358
409
  if (json === null)
359
- return "";
410
+ return nullAsZeroValue ? "" : undefined;
360
411
  if (typeof json !== "string") {
361
412
  break;
362
413
  }
@@ -372,7 +423,9 @@ function readScalar(type, json, longType) {
372
423
  // bytes: JSON value will be the data encoded as a string using standard base64 encoding with paddings.
373
424
  // Either standard or URL-safe base64 encoding with/without paddings are accepted.
374
425
  case field_js_1.ScalarType.BYTES:
375
- if (json === null || json === "")
426
+ if (json === null)
427
+ return nullAsZeroValue ? new Uint8Array(0) : undefined;
428
+ if (json === "")
376
429
  return new Uint8Array(0);
377
430
  if (typeof json !== "string")
378
431
  break;
@@ -380,10 +433,14 @@ function readScalar(type, json, longType) {
380
433
  }
381
434
  throw new Error();
382
435
  }
383
- function readEnum(type, json, ignoreUnknownFields) {
436
+ // If the argument "nullAsZeroValue" is `true`, this function returns the first
437
+ // enum value for JSON null. If the argument is `false`, this function returns
438
+ // `undefined`.
439
+ function readEnum(type, json, ignoreUnknownFields, nullAsZeroValue) {
384
440
  if (json === null) {
385
- // proto3 requires 0 to be default value for all enums
386
- return 0;
441
+ // proto3 requires 0 to be default value for all enums (which is required to be the first value).
442
+ // proto2 uses the first value (at least with protoc-gen-go).
443
+ return nullAsZeroValue ? type.values[0].no : undefined;
387
444
  }
388
445
  // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
389
446
  switch (typeof json) {
@@ -402,12 +459,12 @@ function readEnum(type, json, ignoreUnknownFields) {
402
459
  }
403
460
  throw new Error(`cannot decode enum ${type.typeName} from JSON: ${debugJsonValue(json)}`);
404
461
  }
405
- function writeEnum(type, value, emitIntrinsicDefault, enumAsInteger) {
462
+ function writeEnum(type, value, emitZeroValue, enumAsInteger) {
406
463
  var _a;
407
464
  if (value === undefined) {
408
465
  return value;
409
466
  }
410
- if (value === 0 && !emitIntrinsicDefault) {
467
+ if (!emitZeroValue && type.values[0].no === value) {
411
468
  // proto3 requires 0 to be default value for all enums
412
469
  return undefined;
413
470
  }
@@ -420,7 +477,7 @@ function writeEnum(type, value, emitIntrinsicDefault, enumAsInteger) {
420
477
  const val = type.findNumber(value);
421
478
  return (_a = val === null || val === void 0 ? void 0 : val.name) !== null && _a !== void 0 ? _a : value; // if we don't know the enum value, just return the number
422
479
  }
423
- function writeScalar(type, value, emitIntrinsicDefault) {
480
+ function writeScalar(type, value, emitZeroValue) {
424
481
  if (value === undefined) {
425
482
  return undefined;
426
483
  }
@@ -432,7 +489,7 @@ function writeScalar(type, value, emitIntrinsicDefault) {
432
489
  case field_js_1.ScalarType.FIXED32:
433
490
  case field_js_1.ScalarType.UINT32:
434
491
  (0, assert_js_1.assert)(typeof value == "number");
435
- return value != 0 || emitIntrinsicDefault ? value : undefined;
492
+ return value != 0 || emitZeroValue ? value : undefined;
436
493
  // float, double: JSON value will be a number or one of the special string values "NaN", "Infinity", and "-Infinity".
437
494
  // Either numbers or strings are accepted. Exponent notation is also accepted.
438
495
  case field_js_1.ScalarType.FLOAT:
@@ -445,15 +502,15 @@ function writeScalar(type, value, emitIntrinsicDefault) {
445
502
  return "Infinity";
446
503
  if (value === Number.NEGATIVE_INFINITY)
447
504
  return "-Infinity";
448
- return value !== 0 || emitIntrinsicDefault ? value : undefined;
505
+ return value !== 0 || emitZeroValue ? value : undefined;
449
506
  // string:
450
507
  case field_js_1.ScalarType.STRING:
451
508
  (0, assert_js_1.assert)(typeof value == "string");
452
- return value.length > 0 || emitIntrinsicDefault ? value : undefined;
509
+ return value.length > 0 || emitZeroValue ? value : undefined;
453
510
  // bool:
454
511
  case field_js_1.ScalarType.BOOL:
455
512
  (0, assert_js_1.assert)(typeof value == "boolean");
456
- return value || emitIntrinsicDefault ? value : undefined;
513
+ return value || emitZeroValue ? value : undefined;
457
514
  // JSON value will be a decimal string. Either numbers or strings are accepted.
458
515
  case field_js_1.ScalarType.UINT64:
459
516
  case field_js_1.ScalarType.FIXED64:
@@ -466,14 +523,12 @@ function writeScalar(type, value, emitIntrinsicDefault) {
466
523
  // We use implicit conversion with `value != 0` to catch both 0n and "0"
467
524
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
468
525
  // @ts-ignore
469
- return emitIntrinsicDefault || value != 0
470
- ? value.toString(10)
471
- : undefined;
526
+ return emitZeroValue || value != 0 ? value.toString(10) : undefined;
472
527
  // bytes: JSON value will be the data encoded as a string using standard base64 encoding with paddings.
473
528
  // Either standard or URL-safe base64 encoding with/without paddings are accepted.
474
529
  case field_js_1.ScalarType.BYTES:
475
530
  (0, assert_js_1.assert)(value instanceof Uint8Array);
476
- return emitIntrinsicDefault || value.byteLength > 0
531
+ return emitZeroValue || value.byteLength > 0
477
532
  ? proto_base64_js_1.protoBase64.enc(value)
478
533
  : undefined;
479
534
  }
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- // Copyright 2021-2023 Buf Technologies, Inc.
2
+ // Copyright 2021-2024 Buf Technologies, Inc.
3
3
  //
4
4
  // Licensed under the Apache License, Version 2.0 (the "License");
5
5
  // you may not use this file except in compliance with the License.
@@ -19,7 +19,8 @@ const assert_js_1 = require("./assert.js");
19
19
  const json_format_common_js_1 = require("./json-format-common.js");
20
20
  /* eslint-disable no-case-declarations, @typescript-eslint/restrict-plus-operands,@typescript-eslint/no-explicit-any,@typescript-eslint/no-unsafe-return,@typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-argument */
21
21
  function makeJsonFormatProto2() {
22
- return (0, json_format_common_js_1.makeJsonFormatCommon)((writeEnum, writeScalar) => {
22
+ // TODO field presence: merge this function with proto3. the reading side already switches behavior on the nullAsZeroValue argument.
23
+ return (0, json_format_common_js_1.makeJsonFormatCommon)(false, (writeEnum, writeScalar) => {
23
24
  return function writeField(field, value, options) {
24
25
  if (field.kind == "map") {
25
26
  const jsonObj = {};
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- // Copyright 2021-2023 Buf Technologies, Inc.
2
+ // Copyright 2021-2024 Buf Technologies, Inc.
3
3
  //
4
4
  // Licensed under the Apache License, Version 2.0 (the "License");
5
5
  // you may not use this file except in compliance with the License.
@@ -19,7 +19,8 @@ const assert_js_1 = require("./assert.js");
19
19
  const json_format_common_js_1 = require("./json-format-common.js");
20
20
  /* eslint-disable no-case-declarations, @typescript-eslint/restrict-plus-operands,@typescript-eslint/no-explicit-any,@typescript-eslint/no-unsafe-return,@typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-argument */
21
21
  function makeJsonFormatProto3() {
22
- return (0, json_format_common_js_1.makeJsonFormatCommon)((writeEnum, writeScalar) => {
22
+ // TODO field presence: merge this function with proto2. the reading side already switches behavior on the nullAsZeroValue argument.
23
+ return (0, json_format_common_js_1.makeJsonFormatCommon)(true, (writeEnum, writeScalar) => {
23
24
  return function writeField(field, value, options) {
24
25
  if (field.kind == "map") {
25
26
  const jsonObj = {};
@@ -66,7 +67,7 @@ function makeJsonFormatProto3() {
66
67
  break;
67
68
  case "message":
68
69
  for (let i = 0; i < value.length; i++) {
69
- jsonArr.push((0, field_wrapper_js_1.wrapField)(field.T, value[i]).toJson(options));
70
+ jsonArr.push(value[i].toJson(options));
70
71
  }
71
72
  break;
72
73
  }
@@ -75,15 +76,16 @@ function makeJsonFormatProto3() {
75
76
  : undefined;
76
77
  }
77
78
  else {
79
+ if (value === undefined) {
80
+ return undefined;
81
+ }
78
82
  switch (field.kind) {
79
83
  case "scalar":
80
84
  return writeScalar(field.T, value, !!field.oneof || field.opt || options.emitDefaultValues);
81
85
  case "enum":
82
86
  return writeEnum(field.T, value, !!field.oneof || field.opt || options.emitDefaultValues, options.enumAsInteger);
83
87
  case "message":
84
- return value !== undefined
85
- ? (0, field_wrapper_js_1.wrapField)(field.T, value).toJson(options)
86
- : undefined;
88
+ return (0, field_wrapper_js_1.wrapField)(field.T, value).toJson(options);
87
89
  }
88
90
  }
89
91
  };
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- // Copyright 2021-2023 Buf Technologies, Inc.
2
+ // Copyright 2021-2024 Buf Technologies, Inc.
3
3
  //
4
4
  // Licensed under the Apache License, Version 2.0 (the "License");
5
5
  // you may not use this file except in compliance with the License.
@@ -1,4 +1,4 @@
1
- import type { DescEnum, DescEnumValue, DescField, DescMessage, DescService } from "../descriptor-set.js";
1
+ import type { DescEnum, DescEnumValue, DescExtension, DescField, DescMessage, DescService } from "../descriptor-set.js";
2
2
  import type { DescMethod, DescOneof } from "../descriptor-set.js";
3
3
  /**
4
4
  * Returns the name of a protobuf element in generated code.
@@ -8,7 +8,7 @@ import type { DescMethod, DescOneof } from "../descriptor-set.js";
8
8
  * the type name. For nested messages and enumerations, the names are joined
9
9
  * with an underscore. For methods, the first character is made lowercase.
10
10
  */
11
- export declare function localName(desc: DescEnum | DescEnumValue | DescMessage | DescOneof | DescField | DescService | DescMethod): string;
11
+ export declare function localName(desc: DescEnum | DescEnumValue | DescMessage | DescExtension | DescOneof | DescField | DescService | DescMethod): string;
12
12
  /**
13
13
  * Returns the name of a field in generated code.
14
14
  */