@bufbuild/protobuf 1.7.2 → 1.9.0

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 (127) hide show
  1. package/dist/cjs/binary-encoding.d.ts +2 -2
  2. package/dist/cjs/codegen-info.d.ts +6 -1
  3. package/dist/cjs/codegen-info.js +4 -3
  4. package/dist/cjs/create-descriptor-set.js +45 -33
  5. package/dist/cjs/create-registry-from-desc.js +60 -110
  6. package/dist/cjs/descriptor-set.d.ts +13 -9
  7. package/dist/cjs/field.d.ts +25 -51
  8. package/dist/cjs/field.js +0 -66
  9. package/dist/cjs/google/protobuf/compiler/plugin_pb.d.ts +18 -0
  10. package/dist/cjs/google/protobuf/compiler/plugin_pb.js +2 -0
  11. package/dist/cjs/google/protobuf/descriptor_pb.d.ts +33 -33
  12. package/dist/cjs/google/protobuf/descriptor_pb.js +23 -10
  13. package/dist/cjs/google/protobuf/struct_pb.js +1 -1
  14. package/dist/cjs/google/protobuf/type_pb.js +1 -1
  15. package/dist/cjs/google/protobuf/wrappers_pb.js +19 -19
  16. package/dist/cjs/index.d.ts +4 -2
  17. package/dist/cjs/index.js +6 -4
  18. package/dist/cjs/is-message.d.ts +22 -0
  19. package/dist/cjs/is-message.js +52 -0
  20. package/dist/cjs/json-format.d.ts +1 -2
  21. package/dist/cjs/message.d.ts +1 -0
  22. package/dist/cjs/message.js +1 -0
  23. package/dist/cjs/private/binary-format.d.ts +7 -0
  24. package/dist/cjs/private/{binary-format-common.js → binary-format.js} +150 -53
  25. package/dist/cjs/private/extensions.js +1 -1
  26. package/dist/cjs/private/feature-set.js +1 -1
  27. package/dist/cjs/private/field-normalize.d.ts +9 -0
  28. package/dist/cjs/private/field-normalize.js +69 -0
  29. package/dist/cjs/private/field-wrapper.d.ts +1 -1
  30. package/dist/cjs/private/field-wrapper.js +12 -12
  31. package/dist/cjs/private/field.d.ts +1 -0
  32. package/dist/cjs/private/field.js +1 -0
  33. package/dist/cjs/private/json-format.d.ts +2 -0
  34. package/dist/cjs/private/{json-format-common.js → json-format.js} +261 -170
  35. package/dist/cjs/private/names.js +3 -3
  36. package/dist/cjs/private/proto-runtime.d.ts +1 -1
  37. package/dist/cjs/private/proto-runtime.js +8 -4
  38. package/dist/cjs/private/reflect.d.ts +9 -0
  39. package/dist/cjs/private/reflect.js +79 -0
  40. package/dist/cjs/private/reify-wkt.js +11 -11
  41. package/dist/cjs/private/scalars.d.ts +9 -18
  42. package/dist/cjs/private/scalars.js +36 -80
  43. package/dist/cjs/private/text-format.d.ts +1 -1
  44. package/dist/cjs/private/text-format.js +17 -17
  45. package/dist/cjs/private/util-common.js +20 -14
  46. package/dist/cjs/proto-delimited.js +2 -3
  47. package/dist/cjs/proto2.js +29 -68
  48. package/dist/cjs/proto3.js +30 -77
  49. package/dist/cjs/scalar.d.ts +53 -0
  50. package/dist/cjs/scalar.js +81 -0
  51. package/dist/cjs/to-plain-message.js +3 -4
  52. package/dist/esm/binary-encoding.d.ts +2 -2
  53. package/dist/esm/codegen-info.d.ts +6 -1
  54. package/dist/esm/codegen-info.js +6 -5
  55. package/dist/esm/create-descriptor-set.js +22 -10
  56. package/dist/esm/create-registry-from-desc.js +62 -111
  57. package/dist/esm/descriptor-set.d.ts +13 -9
  58. package/dist/esm/descriptor-set.js +1 -1
  59. package/dist/esm/field.d.ts +25 -51
  60. package/dist/esm/field.js +1 -65
  61. package/dist/esm/google/protobuf/compiler/plugin_pb.d.ts +18 -0
  62. package/dist/esm/google/protobuf/compiler/plugin_pb.js +2 -0
  63. package/dist/esm/google/protobuf/descriptor_pb.d.ts +33 -33
  64. package/dist/esm/google/protobuf/descriptor_pb.js +23 -10
  65. package/dist/esm/google/protobuf/struct_pb.js +1 -1
  66. package/dist/esm/google/protobuf/type_pb.js +1 -1
  67. package/dist/esm/google/protobuf/wrappers_pb.js +1 -1
  68. package/dist/esm/index.d.ts +4 -2
  69. package/dist/esm/index.js +2 -1
  70. package/dist/esm/is-message.d.ts +22 -0
  71. package/dist/esm/is-message.js +48 -0
  72. package/dist/esm/json-format.d.ts +1 -2
  73. package/dist/esm/json-format.js +1 -1
  74. package/dist/esm/message.d.ts +1 -0
  75. package/dist/esm/message.js +1 -0
  76. package/dist/esm/private/binary-format.d.ts +7 -0
  77. package/dist/esm/private/{binary-format-common.js → binary-format.js} +126 -25
  78. package/dist/esm/private/extensions.js +2 -2
  79. package/dist/esm/private/feature-set.js +1 -1
  80. package/dist/esm/private/field-normalize.d.ts +9 -0
  81. package/dist/esm/private/field-normalize.js +65 -0
  82. package/dist/esm/private/field-wrapper.d.ts +1 -1
  83. package/dist/esm/private/field-wrapper.js +3 -2
  84. package/dist/esm/private/field.d.ts +1 -0
  85. package/dist/esm/private/field.js +1 -0
  86. package/dist/esm/private/json-format.d.ts +2 -0
  87. package/dist/esm/private/{json-format-common.js → json-format.js} +228 -136
  88. package/dist/esm/private/names.js +3 -3
  89. package/dist/esm/private/proto-runtime.d.ts +1 -1
  90. package/dist/esm/private/proto-runtime.js +8 -4
  91. package/dist/esm/private/reflect.d.ts +9 -0
  92. package/dist/esm/private/reflect.js +74 -0
  93. package/dist/esm/private/reify-wkt.js +1 -1
  94. package/dist/esm/private/scalars.d.ts +9 -18
  95. package/dist/esm/private/scalars.js +15 -59
  96. package/dist/esm/private/text-format.d.ts +1 -1
  97. package/dist/esm/private/text-format.js +1 -1
  98. package/dist/esm/private/util-common.js +13 -6
  99. package/dist/esm/proto-delimited.js +2 -3
  100. package/dist/esm/proto2.js +29 -68
  101. package/dist/esm/proto3.js +31 -78
  102. package/dist/esm/scalar.d.ts +53 -0
  103. package/dist/esm/scalar.js +78 -0
  104. package/dist/esm/to-plain-message.js +3 -2
  105. package/package.json +4 -10
  106. package/dist/cjs/private/binary-format-common.d.ts +0 -13
  107. package/dist/cjs/private/binary-format-proto2.d.ts +0 -2
  108. package/dist/cjs/private/binary-format-proto2.js +0 -91
  109. package/dist/cjs/private/binary-format-proto3.d.ts +0 -2
  110. package/dist/cjs/private/binary-format-proto3.js +0 -83
  111. package/dist/cjs/private/json-format-common.d.ts +0 -9
  112. package/dist/cjs/private/json-format-proto2.d.ts +0 -2
  113. package/dist/cjs/private/json-format-proto2.js +0 -103
  114. package/dist/cjs/private/json-format-proto3.d.ts +0 -2
  115. package/dist/cjs/private/json-format-proto3.js +0 -94
  116. package/dist/esm/private/binary-format-common.d.ts +0 -13
  117. package/dist/esm/private/binary-format-proto2.d.ts +0 -2
  118. package/dist/esm/private/binary-format-proto2.js +0 -87
  119. package/dist/esm/private/binary-format-proto3.d.ts +0 -2
  120. package/dist/esm/private/binary-format-proto3.js +0 -79
  121. package/dist/esm/private/json-format-common.d.ts +0 -9
  122. package/dist/esm/private/json-format-proto2.d.ts +0 -2
  123. package/dist/esm/private/json-format-proto2.js +0 -99
  124. package/dist/esm/private/json-format-proto3.d.ts +0 -2
  125. package/dist/esm/private/json-format-proto3.js +0 -90
  126. package/dist/proxy/index.d.ts +0 -1
  127. package/dist/proxy/index.js +0 -1
@@ -13,15 +13,19 @@
13
13
  // See the License for the specific language governing permissions and
14
14
  // limitations under the License.
15
15
  Object.defineProperty(exports, "__esModule", { value: true });
16
- exports.makeJsonFormatCommon = void 0;
17
- const message_js_1 = require("../message.js");
18
- const field_js_1 = require("../field.js");
16
+ exports.makeJsonFormat = void 0;
19
17
  const assert_js_1 = require("./assert.js");
20
18
  const proto_int64_js_1 = require("../proto-int64.js");
21
19
  const proto_base64_js_1 = require("../proto-base64.js");
22
20
  const extensions_js_1 = require("./extensions.js");
23
21
  const extension_accessor_js_1 = require("../extension-accessor.js");
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 */
22
+ const reflect_js_1 = require("./reflect.js");
23
+ const field_wrapper_js_1 = require("./field-wrapper.js");
24
+ const scalars_js_1 = require("./scalars.js");
25
+ const scalars_js_2 = require("./scalars.js");
26
+ const scalar_js_1 = require("../scalar.js");
27
+ const is_message_js_1 = require("../is-message.js");
28
+ /* eslint-disable no-case-declarations,@typescript-eslint/no-unsafe-argument,@typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-call */
25
29
  // Default options for parsing JSON.
26
30
  const jsonReadDefaults = {
27
31
  ignoreUnknownFields: false,
@@ -39,8 +43,9 @@ function makeReadOptions(options) {
39
43
  function makeWriteOptions(options) {
40
44
  return options ? Object.assign(Object.assign({}, jsonWriteDefaults), options) : jsonWriteDefaults;
41
45
  }
42
- function makeJsonFormatCommon(nullAsZeroValue, makeWriteField) {
43
- const writeField = makeWriteField(writeEnum, writeScalar);
46
+ const tokenNull = Symbol();
47
+ const tokenIgnoredUnknownEnum = Symbol();
48
+ function makeJsonFormat() {
44
49
  return {
45
50
  makeReadOptions,
46
51
  makeWriteOptions,
@@ -65,7 +70,7 @@ function makeJsonFormatCommon(nullAsZeroValue, makeWriteField) {
65
70
  }
66
71
  oneofSeen.set(field.oneof, jsonKey);
67
72
  }
68
- readField(message, jsonValue, field, options, type, nullAsZeroValue);
73
+ readField(message, jsonValue, field, options, type);
69
74
  }
70
75
  else {
71
76
  let found = false;
@@ -76,7 +81,7 @@ function makeJsonFormatCommon(nullAsZeroValue, makeWriteField) {
76
81
  if (ext && ext.extendee.typeName == type.typeName) {
77
82
  found = true;
78
83
  const [container, get] = (0, extensions_js_1.createExtensionContainer)(ext);
79
- readField(container, jsonValue, ext.field, options, ext, true);
84
+ readField(container, jsonValue, ext.field, options, ext);
80
85
  // We pass on the options as BinaryReadOptions/BinaryWriteOptions,
81
86
  // so that users can bring their own binary reader and writer factories
82
87
  // if necessary.
@@ -95,23 +100,23 @@ function makeJsonFormatCommon(nullAsZeroValue, makeWriteField) {
95
100
  const json = {};
96
101
  let field;
97
102
  try {
98
- for (const member of type.fields.byMember()) {
99
- let jsonValue;
100
- if (member.kind == "oneof") {
101
- const oneof = message[member.localName];
102
- if (oneof.value === undefined) {
103
+ for (field of type.fields.byNumber()) {
104
+ if (!(0, reflect_js_1.isFieldSet)(field, message)) {
105
+ // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
106
+ if (field.req) {
107
+ throw `required field not set`;
108
+ }
109
+ if (!options.emitDefaultValues) {
103
110
  continue;
104
111
  }
105
- field = member.findField(oneof.case);
106
- if (!field) {
107
- throw "oneof case not found: " + oneof.case;
112
+ if (!canEmitFieldDefaultValue(field)) {
113
+ continue;
108
114
  }
109
- jsonValue = writeField(field, oneof.value, options);
110
- }
111
- else {
112
- field = member;
113
- jsonValue = writeField(field, message[field.localName], options);
114
115
  }
116
+ const value = field.oneof
117
+ ? message[field.oneof.localName].value
118
+ : message[field.localName];
119
+ const jsonValue = writeField(field, value, options);
115
120
  if (jsonValue !== undefined) {
116
121
  json[options.useProtoFieldName ? field.name : field.jsonName] =
117
122
  jsonValue;
@@ -142,12 +147,28 @@ function makeJsonFormatCommon(nullAsZeroValue, makeWriteField) {
142
147
  }
143
148
  return json;
144
149
  },
145
- readScalar: (type, json, longType) => readScalar(type, json, longType, nullAsZeroValue), // eslint-disable-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-return
146
- writeScalar,
150
+ readScalar(type, json, longType) {
151
+ // The signature of our internal function has changed. For backwards-
152
+ // compatibility, we support the old form that is part of the public API
153
+ // through the interface JsonFormat.
154
+ return readScalar(type, json, longType !== null && longType !== void 0 ? longType : scalar_js_1.LongType.BIGINT, true);
155
+ },
156
+ writeScalar(type, value, emitDefaultValues) {
157
+ // The signature of our internal function has changed. For backwards-
158
+ // compatibility, we support the old form that is part of the public API
159
+ // through the interface JsonFormat.
160
+ if (value === undefined) {
161
+ return undefined;
162
+ }
163
+ if (emitDefaultValues || (0, scalars_js_2.isScalarZeroValue)(type, value)) {
164
+ return writeScalar(type, value);
165
+ }
166
+ return undefined;
167
+ },
147
168
  debug: debugJsonValue,
148
169
  };
149
170
  }
150
- exports.makeJsonFormatCommon = makeJsonFormatCommon;
171
+ exports.makeJsonFormat = makeJsonFormat;
151
172
  function debugJsonValue(json) {
152
173
  if (json === null) {
153
174
  return "null";
@@ -162,50 +183,38 @@ function debugJsonValue(json) {
162
183
  }
163
184
  }
164
185
  // 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) {
186
+ // The "parentType" argument is only used to provide context in errors.
187
+ function readField(target, jsonValue, field, options, parentType) {
171
188
  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
189
  if (field.repeated) {
190
+ (0, assert_js_1.assert)(field.kind != "map");
181
191
  if (jsonValue === null) {
182
192
  return;
183
193
  }
184
194
  if (!Array.isArray(jsonValue)) {
185
- throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonValue)}`);
195
+ throw new Error(`cannot decode field ${parentType.typeName}.${field.name} from JSON: ${debugJsonValue(jsonValue)}`);
186
196
  }
187
197
  const targetArray = target[localName];
188
198
  for (const jsonItem of jsonValue) {
189
199
  if (jsonItem === null) {
190
- throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonItem)}`);
200
+ throw new Error(`cannot decode field ${parentType.typeName}.${field.name} from JSON: ${debugJsonValue(jsonItem)}`);
191
201
  }
192
- let val;
193
- // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check -- "map" is invalid for repeated fields
194
202
  switch (field.kind) {
195
203
  case "message":
196
- val = field.T.fromJson(jsonItem, options);
204
+ targetArray.push(field.T.fromJson(jsonItem, options));
197
205
  break;
198
206
  case "enum":
199
- val = readEnum(field.T, jsonItem, options.ignoreUnknownFields, true);
200
- if (val === undefined)
201
- continue;
207
+ const enumValue = readEnum(field.T, jsonItem, options.ignoreUnknownFields, true);
208
+ if (enumValue !== tokenIgnoredUnknownEnum) {
209
+ targetArray.push(enumValue);
210
+ }
202
211
  break;
203
212
  case "scalar":
204
213
  try {
205
- val = readScalar(field.T, jsonItem, field.L, true);
214
+ targetArray.push(readScalar(field.T, jsonItem, field.L, true));
206
215
  }
207
216
  catch (e) {
208
- let m = `cannot decode field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonItem)}`;
217
+ let m = `cannot decode field ${parentType.typeName}.${field.name} from JSON: ${debugJsonValue(jsonItem)}`;
209
218
  if (e instanceof Error && e.message.length > 0) {
210
219
  m += `: ${e.message}`;
211
220
  }
@@ -213,7 +222,6 @@ jsonValue, field, options, type, nullAsZeroValue) {
213
222
  }
214
223
  break;
215
224
  }
216
- targetArray.push(val);
217
225
  }
218
226
  }
219
227
  else if (field.kind == "map") {
@@ -221,29 +229,40 @@ jsonValue, field, options, type, nullAsZeroValue) {
221
229
  return;
222
230
  }
223
231
  if (typeof jsonValue != "object" || Array.isArray(jsonValue)) {
224
- throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonValue)}`);
232
+ throw new Error(`cannot decode field ${parentType.typeName}.${field.name} from JSON: ${debugJsonValue(jsonValue)}`);
225
233
  }
226
234
  const targetMap = target[localName];
227
235
  for (const [jsonMapKey, jsonMapValue] of Object.entries(jsonValue)) {
228
236
  if (jsonMapValue === null) {
229
- throw new Error(`cannot decode field ${type.typeName}.${field.name} from JSON: map value null`);
237
+ throw new Error(`cannot decode field ${parentType.typeName}.${field.name} from JSON: map value null`);
238
+ }
239
+ let key;
240
+ try {
241
+ key = readMapKey(field.K, jsonMapKey);
242
+ }
243
+ catch (e) {
244
+ let m = `cannot decode map key for field ${parentType.typeName}.${field.name} from JSON: ${debugJsonValue(jsonValue)}`;
245
+ if (e instanceof Error && e.message.length > 0) {
246
+ m += `: ${e.message}`;
247
+ }
248
+ throw new Error(m);
230
249
  }
231
- let val;
232
250
  switch (field.V.kind) {
233
251
  case "message":
234
- val = field.V.T.fromJson(jsonMapValue, options);
252
+ targetMap[key] = field.V.T.fromJson(jsonMapValue, options);
235
253
  break;
236
254
  case "enum":
237
- val = readEnum(field.V.T, jsonMapValue, options.ignoreUnknownFields, true);
238
- if (val === undefined)
239
- continue;
255
+ const enumValue = readEnum(field.V.T, jsonMapValue, options.ignoreUnknownFields, true);
256
+ if (enumValue !== tokenIgnoredUnknownEnum) {
257
+ targetMap[key] = enumValue;
258
+ }
240
259
  break;
241
260
  case "scalar":
242
261
  try {
243
- val = readScalar(field.V.T, jsonMapValue, field_js_1.LongType.BIGINT, true);
262
+ targetMap[key] = readScalar(field.V.T, jsonMapValue, scalar_js_1.LongType.BIGINT, true);
244
263
  }
245
264
  catch (e) {
246
- let m = `cannot decode map value for field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonValue)}`;
265
+ let m = `cannot decode map value for field ${parentType.typeName}.${field.name} from JSON: ${debugJsonValue(jsonValue)}`;
247
266
  if (e instanceof Error && e.message.length > 0) {
248
267
  m += `: ${e.message}`;
249
268
  }
@@ -251,57 +270,59 @@ jsonValue, field, options, type, nullAsZeroValue) {
251
270
  }
252
271
  break;
253
272
  }
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
273
  }
271
274
  }
272
275
  else {
276
+ if (field.oneof) {
277
+ target = target[field.oneof.localName] = { case: localName };
278
+ localName = "value";
279
+ }
273
280
  switch (field.kind) {
274
281
  case "message":
275
282
  const messageType = field.T;
276
283
  if (jsonValue === null &&
277
284
  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
285
  return;
282
286
  }
283
- if (target[localName] instanceof message_js_1.Message) {
284
- target[localName].fromJson(jsonValue, options);
287
+ let currentValue = target[localName];
288
+ if ((0, is_message_js_1.isMessage)(currentValue)) {
289
+ currentValue.fromJson(jsonValue, options);
285
290
  }
286
291
  else {
287
- target[localName] = messageType.fromJson(jsonValue, options);
292
+ target[localName] = currentValue = messageType.fromJson(jsonValue, options);
288
293
  if (messageType.fieldWrapper && !field.oneof) {
289
- target[localName] = messageType.fieldWrapper.unwrapField(target[localName]);
294
+ target[localName] =
295
+ messageType.fieldWrapper.unwrapField(currentValue);
290
296
  }
291
297
  }
292
298
  break;
293
299
  case "enum":
294
- const enumValue = readEnum(field.T, jsonValue, options.ignoreUnknownFields, nullAsZeroValue);
295
- if (enumValue !== undefined) {
296
- target[localName] = enumValue;
300
+ const enumValue = readEnum(field.T, jsonValue, options.ignoreUnknownFields, false);
301
+ switch (enumValue) {
302
+ case tokenNull:
303
+ (0, reflect_js_1.clearField)(field, target);
304
+ break;
305
+ case tokenIgnoredUnknownEnum:
306
+ break;
307
+ default:
308
+ target[localName] = enumValue;
309
+ break;
297
310
  }
298
311
  break;
299
312
  case "scalar":
300
313
  try {
301
- target[localName] = readScalar(field.T, jsonValue, field.L, nullAsZeroValue);
314
+ const scalarValue = readScalar(field.T, jsonValue, field.L, false);
315
+ switch (scalarValue) {
316
+ case tokenNull:
317
+ (0, reflect_js_1.clearField)(field, target);
318
+ break;
319
+ default:
320
+ target[localName] = scalarValue;
321
+ break;
322
+ }
302
323
  }
303
324
  catch (e) {
304
- let m = `cannot decode field ${type.typeName}.${field.name} from JSON: ${debugJsonValue(jsonValue)}`;
325
+ let m = `cannot decode field ${parentType.typeName}.${field.name} from JSON: ${debugJsonValue(jsonValue)}`;
305
326
  if (e instanceof Error && e.message.length > 0) {
306
327
  m += `: ${e.message}`;
307
328
  }
@@ -311,21 +332,34 @@ jsonValue, field, options, type, nullAsZeroValue) {
311
332
  }
312
333
  }
313
334
  }
314
- // May throw an error. If the error message is non-blank, it should be shown.
315
- // It is up to the caller to provide context.
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.
335
+ function readMapKey(type, json) {
336
+ if (type === scalar_js_1.ScalarType.BOOL) {
337
+ // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
338
+ switch (json) {
339
+ case "true":
340
+ json = true;
341
+ break;
342
+ case "false":
343
+ json = false;
344
+ break;
345
+ }
346
+ }
347
+ return readScalar(type, json, scalar_js_1.LongType.BIGINT, true).toString();
348
+ }
319
349
  function readScalar(type, json, longType, nullAsZeroValue) {
350
+ if (json === null) {
351
+ if (nullAsZeroValue) {
352
+ return (0, scalars_js_1.scalarZeroValue)(type, longType);
353
+ }
354
+ return tokenNull;
355
+ }
320
356
  // every valid case in the switch below returns, and every fall
321
357
  // through is regarded as a failure.
322
358
  switch (type) {
323
359
  // float, double: JSON value will be a number or one of the special string values "NaN", "Infinity", and "-Infinity".
324
360
  // Either numbers or strings are accepted. Exponent notation is also accepted.
325
- case field_js_1.ScalarType.DOUBLE:
326
- case field_js_1.ScalarType.FLOAT:
327
- if (json === null)
328
- return nullAsZeroValue ? 0.0 : undefined;
361
+ case scalar_js_1.ScalarType.DOUBLE:
362
+ case scalar_js_1.ScalarType.FLOAT:
329
363
  if (json === "NaN")
330
364
  return Number.NaN;
331
365
  if (json === "Infinity")
@@ -352,17 +386,15 @@ function readScalar(type, json, longType, nullAsZeroValue) {
352
386
  // infinity and -infinity are handled by string representation above, so this is an error
353
387
  break;
354
388
  }
355
- if (type == field_js_1.ScalarType.FLOAT)
389
+ if (type == scalar_js_1.ScalarType.FLOAT)
356
390
  (0, assert_js_1.assertFloat32)(float);
357
391
  return float;
358
392
  // int32, fixed32, uint32: JSON value will be a decimal number. Either numbers or strings are accepted.
359
- case field_js_1.ScalarType.INT32:
360
- case field_js_1.ScalarType.FIXED32:
361
- case field_js_1.ScalarType.SFIXED32:
362
- case field_js_1.ScalarType.SINT32:
363
- case field_js_1.ScalarType.UINT32:
364
- if (json === null)
365
- return nullAsZeroValue ? 0 : undefined;
393
+ case scalar_js_1.ScalarType.INT32:
394
+ case scalar_js_1.ScalarType.FIXED32:
395
+ case scalar_js_1.ScalarType.SFIXED32:
396
+ case scalar_js_1.ScalarType.SINT32:
397
+ case scalar_js_1.ScalarType.UINT32:
366
398
  let int32;
367
399
  if (typeof json == "number")
368
400
  int32 = json;
@@ -372,42 +404,34 @@ function readScalar(type, json, longType, nullAsZeroValue) {
372
404
  }
373
405
  if (int32 === undefined)
374
406
  break;
375
- if (type == field_js_1.ScalarType.UINT32)
407
+ if (type == scalar_js_1.ScalarType.UINT32 || type == scalar_js_1.ScalarType.FIXED32)
376
408
  (0, assert_js_1.assertUInt32)(int32);
377
409
  else
378
410
  (0, assert_js_1.assertInt32)(int32);
379
411
  return int32;
380
412
  // int64, fixed64, uint64: JSON value will be a decimal string. Either numbers or strings are accepted.
381
- case field_js_1.ScalarType.INT64:
382
- case field_js_1.ScalarType.SFIXED64:
383
- case field_js_1.ScalarType.SINT64:
384
- if (json === null)
385
- return nullAsZeroValue ? proto_int64_js_1.protoInt64.zero : undefined;
413
+ case scalar_js_1.ScalarType.INT64:
414
+ case scalar_js_1.ScalarType.SFIXED64:
415
+ case scalar_js_1.ScalarType.SINT64:
386
416
  if (typeof json != "number" && typeof json != "string")
387
417
  break;
388
418
  const long = proto_int64_js_1.protoInt64.parse(json);
389
419
  // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
390
420
  return longType ? long.toString() : long;
391
- case field_js_1.ScalarType.FIXED64:
392
- case field_js_1.ScalarType.UINT64:
393
- if (json === null)
394
- return nullAsZeroValue ? proto_int64_js_1.protoInt64.zero : undefined;
421
+ case scalar_js_1.ScalarType.FIXED64:
422
+ case scalar_js_1.ScalarType.UINT64:
395
423
  if (typeof json != "number" && typeof json != "string")
396
424
  break;
397
425
  const uLong = proto_int64_js_1.protoInt64.uParse(json);
398
426
  // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
399
427
  return longType ? uLong.toString() : uLong;
400
428
  // bool:
401
- case field_js_1.ScalarType.BOOL:
402
- if (json === null)
403
- return nullAsZeroValue ? false : undefined;
429
+ case scalar_js_1.ScalarType.BOOL:
404
430
  if (typeof json !== "boolean")
405
431
  break;
406
432
  return json;
407
433
  // string:
408
- case field_js_1.ScalarType.STRING:
409
- if (json === null)
410
- return nullAsZeroValue ? "" : undefined;
434
+ case scalar_js_1.ScalarType.STRING:
411
435
  if (typeof json !== "string") {
412
436
  break;
413
437
  }
@@ -422,9 +446,7 @@ function readScalar(type, json, longType, nullAsZeroValue) {
422
446
  return json;
423
447
  // bytes: JSON value will be the data encoded as a string using standard base64 encoding with paddings.
424
448
  // Either standard or URL-safe base64 encoding with/without paddings are accepted.
425
- case field_js_1.ScalarType.BYTES:
426
- if (json === null)
427
- return nullAsZeroValue ? new Uint8Array(0) : undefined;
449
+ case scalar_js_1.ScalarType.BYTES:
428
450
  if (json === "")
429
451
  return new Uint8Array(0);
430
452
  if (typeof json !== "string")
@@ -433,14 +455,12 @@ function readScalar(type, json, longType, nullAsZeroValue) {
433
455
  }
434
456
  throw new Error();
435
457
  }
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
458
  function readEnum(type, json, ignoreUnknownFields, nullAsZeroValue) {
440
459
  if (json === null) {
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;
460
+ if (type.typeName == "google.protobuf.NullValue") {
461
+ return 0; // google.protobuf.NullValue.NULL_VALUE = 0
462
+ }
463
+ return nullAsZeroValue ? type.values[0].no : tokenNull;
444
464
  }
445
465
  // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
446
466
  switch (typeof json) {
@@ -451,50 +471,126 @@ function readEnum(type, json, ignoreUnknownFields, nullAsZeroValue) {
451
471
  break;
452
472
  case "string":
453
473
  const value = type.findName(json);
454
- // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
455
- if (value || ignoreUnknownFields) {
456
- return value === null || value === void 0 ? void 0 : value.no;
474
+ if (value !== undefined) {
475
+ return value.no;
476
+ }
477
+ if (ignoreUnknownFields) {
478
+ return tokenIgnoredUnknownEnum;
457
479
  }
458
480
  break;
459
481
  }
460
482
  throw new Error(`cannot decode enum ${type.typeName} from JSON: ${debugJsonValue(json)}`);
461
483
  }
462
- function writeEnum(type, value, emitZeroValue, enumAsInteger) {
463
- var _a;
464
- if (value === undefined) {
465
- return value;
484
+ // Decide whether an unset field should be emitted with JSON write option `emitDefaultValues`
485
+ function canEmitFieldDefaultValue(field) {
486
+ if (field.repeated || field.kind == "map") {
487
+ // maps are {}, repeated fields are []
488
+ return true;
489
+ }
490
+ if (field.oneof) {
491
+ // oneof fields are never emitted
492
+ return false;
466
493
  }
467
- if (!emitZeroValue && type.values[0].no === value) {
468
- // proto3 requires 0 to be default value for all enums
469
- return undefined;
494
+ if (field.kind == "message") {
495
+ // singular message field are allowed to emit JSON null, but we do not
496
+ return false;
470
497
  }
471
- if (enumAsInteger) {
472
- return value;
498
+ // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
499
+ if (field.opt || field.req) {
500
+ // the field uses explicit presence, so we cannot emit a zero value
501
+ return false;
502
+ }
503
+ return true;
504
+ }
505
+ function writeField(field, value, options) {
506
+ if (field.kind == "map") {
507
+ (0, assert_js_1.assert)(typeof value == "object" && value != null);
508
+ const jsonObj = {};
509
+ const entries = Object.entries(value);
510
+ switch (field.V.kind) {
511
+ case "scalar":
512
+ for (const [entryKey, entryValue] of entries) {
513
+ jsonObj[entryKey.toString()] = writeScalar(field.V.T, entryValue); // JSON standard allows only (double quoted) string as property key
514
+ }
515
+ break;
516
+ case "message":
517
+ for (const [entryKey, entryValue] of entries) {
518
+ // JSON standard allows only (double quoted) string as property key
519
+ jsonObj[entryKey.toString()] = entryValue.toJson(options);
520
+ }
521
+ break;
522
+ case "enum":
523
+ const enumType = field.V.T;
524
+ for (const [entryKey, entryValue] of entries) {
525
+ // JSON standard allows only (double quoted) string as property key
526
+ jsonObj[entryKey.toString()] = writeEnum(enumType, entryValue, options.enumAsInteger);
527
+ }
528
+ break;
529
+ }
530
+ return options.emitDefaultValues || entries.length > 0
531
+ ? jsonObj
532
+ : undefined;
473
533
  }
534
+ if (field.repeated) {
535
+ (0, assert_js_1.assert)(Array.isArray(value));
536
+ const jsonArr = [];
537
+ switch (field.kind) {
538
+ case "scalar":
539
+ for (let i = 0; i < value.length; i++) {
540
+ jsonArr.push(writeScalar(field.T, value[i]));
541
+ }
542
+ break;
543
+ case "enum":
544
+ for (let i = 0; i < value.length; i++) {
545
+ jsonArr.push(writeEnum(field.T, value[i], options.enumAsInteger));
546
+ }
547
+ break;
548
+ case "message":
549
+ for (let i = 0; i < value.length; i++) {
550
+ jsonArr.push(value[i].toJson(options));
551
+ }
552
+ break;
553
+ }
554
+ return options.emitDefaultValues || jsonArr.length > 0
555
+ ? jsonArr
556
+ : undefined;
557
+ }
558
+ switch (field.kind) {
559
+ case "scalar":
560
+ return writeScalar(field.T, value);
561
+ case "enum":
562
+ return writeEnum(field.T, value, options.enumAsInteger);
563
+ case "message":
564
+ return (0, field_wrapper_js_1.wrapField)(field.T, value).toJson(options);
565
+ }
566
+ }
567
+ function writeEnum(type, value, enumAsInteger) {
568
+ var _a;
569
+ (0, assert_js_1.assert)(typeof value == "number");
474
570
  if (type.typeName == "google.protobuf.NullValue") {
475
571
  return null;
476
572
  }
573
+ if (enumAsInteger) {
574
+ return value;
575
+ }
477
576
  const val = type.findNumber(value);
478
577
  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
479
578
  }
480
- function writeScalar(type, value, emitZeroValue) {
481
- if (value === undefined) {
482
- return undefined;
483
- }
579
+ function writeScalar(type, value) {
484
580
  switch (type) {
485
581
  // int32, fixed32, uint32: JSON value will be a decimal number. Either numbers or strings are accepted.
486
- case field_js_1.ScalarType.INT32:
487
- case field_js_1.ScalarType.SFIXED32:
488
- case field_js_1.ScalarType.SINT32:
489
- case field_js_1.ScalarType.FIXED32:
490
- case field_js_1.ScalarType.UINT32:
582
+ case scalar_js_1.ScalarType.INT32:
583
+ case scalar_js_1.ScalarType.SFIXED32:
584
+ case scalar_js_1.ScalarType.SINT32:
585
+ case scalar_js_1.ScalarType.FIXED32:
586
+ case scalar_js_1.ScalarType.UINT32:
491
587
  (0, assert_js_1.assert)(typeof value == "number");
492
- return value != 0 || emitZeroValue ? value : undefined;
588
+ return value;
493
589
  // float, double: JSON value will be a number or one of the special string values "NaN", "Infinity", and "-Infinity".
494
590
  // Either numbers or strings are accepted. Exponent notation is also accepted.
495
- case field_js_1.ScalarType.FLOAT:
591
+ case scalar_js_1.ScalarType.FLOAT:
496
592
  // assertFloat32(value);
497
- case field_js_1.ScalarType.DOUBLE: // eslint-disable-line no-fallthrough
593
+ case scalar_js_1.ScalarType.DOUBLE: // eslint-disable-line no-fallthrough
498
594
  (0, assert_js_1.assert)(typeof value == "number");
499
595
  if (Number.isNaN(value))
500
596
  return "NaN";
@@ -502,34 +598,29 @@ function writeScalar(type, value, emitZeroValue) {
502
598
  return "Infinity";
503
599
  if (value === Number.NEGATIVE_INFINITY)
504
600
  return "-Infinity";
505
- return value !== 0 || emitZeroValue ? value : undefined;
601
+ return value;
506
602
  // string:
507
- case field_js_1.ScalarType.STRING:
603
+ case scalar_js_1.ScalarType.STRING:
508
604
  (0, assert_js_1.assert)(typeof value == "string");
509
- return value.length > 0 || emitZeroValue ? value : undefined;
605
+ return value;
510
606
  // bool:
511
- case field_js_1.ScalarType.BOOL:
607
+ case scalar_js_1.ScalarType.BOOL:
512
608
  (0, assert_js_1.assert)(typeof value == "boolean");
513
- return value || emitZeroValue ? value : undefined;
609
+ return value;
514
610
  // JSON value will be a decimal string. Either numbers or strings are accepted.
515
- case field_js_1.ScalarType.UINT64:
516
- case field_js_1.ScalarType.FIXED64:
517
- case field_js_1.ScalarType.INT64:
518
- case field_js_1.ScalarType.SFIXED64:
519
- case field_js_1.ScalarType.SINT64:
611
+ case scalar_js_1.ScalarType.UINT64:
612
+ case scalar_js_1.ScalarType.FIXED64:
613
+ case scalar_js_1.ScalarType.INT64:
614
+ case scalar_js_1.ScalarType.SFIXED64:
615
+ case scalar_js_1.ScalarType.SINT64:
520
616
  (0, assert_js_1.assert)(typeof value == "bigint" ||
521
617
  typeof value == "string" ||
522
618
  typeof value == "number");
523
- // We use implicit conversion with `value != 0` to catch both 0n and "0"
524
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
525
- // @ts-ignore
526
- return emitZeroValue || value != 0 ? value.toString(10) : undefined;
619
+ return value.toString();
527
620
  // bytes: JSON value will be the data encoded as a string using standard base64 encoding with paddings.
528
621
  // Either standard or URL-safe base64 encoding with/without paddings are accepted.
529
- case field_js_1.ScalarType.BYTES:
622
+ case scalar_js_1.ScalarType.BYTES:
530
623
  (0, assert_js_1.assert)(value instanceof Uint8Array);
531
- return emitZeroValue || value.byteLength > 0
532
- ? proto_base64_js_1.protoBase64.enc(value)
533
- : undefined;
624
+ return proto_base64_js_1.protoBase64.enc(value);
534
625
  }
535
626
  }