@bufbuild/protobuf 2.0.0-alpha.3 → 2.0.0-alpha.4

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.
package/dist/cjs/clone.js CHANGED
@@ -40,18 +40,21 @@ function cloneReflect(i) {
40
40
  break;
41
41
  }
42
42
  case "list":
43
+ // eslint-disable-next-line no-case-declarations
44
+ const list = o.get(f);
43
45
  for (const item of i.get(f)) {
44
- // TODO fix type error
45
- // @ts-expect-error TODO
46
- const err = o.addListItem(f, cloneSingular(f, item));
46
+ const err = list.add(cloneSingular(f, item));
47
47
  if (err) {
48
48
  throw err;
49
49
  }
50
50
  }
51
51
  break;
52
52
  case "map":
53
+ // eslint-disable-next-line no-case-declarations
54
+ const map = o.get(f);
53
55
  for (const entry of i.get(f).entries()) {
54
- const err = o.setMapEntry(f, entry[0], cloneSingular(f, entry[1]));
56
+ // @ts-expect-error TODO fix type error
57
+ const err = map.set(entry[0], cloneSingular(f, entry[1]));
55
58
  if (err) {
56
59
  throw err;
57
60
  }
@@ -27,7 +27,7 @@ export declare function fromBinary<Desc extends DescMessage>(messageDesc: Desc,
27
27
  * If a message field is already present, it will be merged with the
28
28
  * new data.
29
29
  */
30
- export declare function mergeFromBinary<Desc extends DescMessage>(messageDesc: Desc, target: MessageShape<Desc>, bytes: Uint8Array, options?: Partial<BinaryReadOptions>): void;
30
+ export declare function mergeFromBinary<Desc extends DescMessage>(messageDesc: Desc, target: MessageShape<Desc>, bytes: Uint8Array, options?: Partial<BinaryReadOptions>): MessageShape<Desc>;
31
31
  /**
32
32
  * @private
33
33
  */
@@ -45,6 +45,7 @@ exports.fromBinary = fromBinary;
45
45
  */
46
46
  function mergeFromBinary(messageDesc, target, bytes, options) {
47
47
  readMessage((0, reflect_js_1.reflect)(messageDesc, target), new binary_encoding_js_1.BinaryReader(bytes), makeReadOptions(options), false, bytes.byteLength);
48
+ return target;
48
49
  }
49
50
  exports.mergeFromBinary = mergeFromBinary;
50
51
  /**
@@ -99,16 +100,17 @@ function readField(message, reader, field, wireType, options) {
99
100
  message.set(field, readMessageField(reader, options, field, message.get(field)));
100
101
  break;
101
102
  case "list":
102
- readListField(message, reader, options, field, wireType);
103
+ readListField(reader, wireType, message.get(field), options);
103
104
  break;
104
105
  case "map":
105
- readMapEntry(message, field, reader, options);
106
+ readMapEntry(reader, message.get(field), options);
106
107
  break;
107
108
  }
108
109
  }
109
110
  exports.readField = readField;
110
111
  // Read a map field, expecting key field = 1, value field = 2
111
- function readMapEntry(message, field, reader, options) {
112
+ function readMapEntry(reader, map, options) {
113
+ const field = map.field();
112
114
  let key, val;
113
115
  const end = reader.pos + reader.uint32();
114
116
  while (reader.pos < end) {
@@ -148,12 +150,13 @@ function readMapEntry(message, field, reader, options) {
148
150
  break;
149
151
  }
150
152
  }
151
- message.setMapEntry(field, key, val);
153
+ map.set(key, val);
152
154
  }
153
- function readListField(message, reader, options, field, wireType) {
155
+ function readListField(reader, wireType, list, options) {
154
156
  var _a;
157
+ const field = list.field();
155
158
  if (field.listKind === "message") {
156
- message.addListItem(field, readMessageField(reader, options, field));
159
+ list.add(readMessageField(reader, options, field));
157
160
  return;
158
161
  }
159
162
  const scalarType = (_a = field.scalar) !== null && _a !== void 0 ? _a : descriptors_js_1.ScalarType.INT32;
@@ -161,12 +164,12 @@ function readListField(message, reader, options, field, wireType) {
161
164
  scalarType != descriptors_js_1.ScalarType.STRING &&
162
165
  scalarType != descriptors_js_1.ScalarType.BYTES;
163
166
  if (!packed) {
164
- message.addListItem(field, readScalar(reader, scalarType));
167
+ list.add(readScalar(reader, scalarType));
165
168
  return;
166
169
  }
167
170
  const e = reader.uint32() + reader.pos;
168
171
  while (reader.pos < e) {
169
- message.addListItem(field, readScalar(reader, scalarType));
172
+ list.add(readScalar(reader, scalarType));
170
173
  }
171
174
  }
172
175
  function readMessageField(reader, options, field, mergeMessage) {
@@ -31,7 +31,7 @@ export declare function fromJsonString<Desc extends DescMessage>(messageDesc: De
31
31
  * If a message field is already present, it will be merged with the
32
32
  * new data.
33
33
  */
34
- export declare function mergeFromJsonString<Desc extends DescMessage>(messageDesc: Desc, target: MessageShape<Desc>, json: string, options?: Partial<JsonReadOptions>): void;
34
+ export declare function mergeFromJsonString<Desc extends DescMessage>(messageDesc: Desc, target: MessageShape<Desc>, json: string, options?: Partial<JsonReadOptions>): MessageShape<Desc>;
35
35
  /**
36
36
  * Parse a message from a JSON value.
37
37
  */
@@ -45,4 +45,4 @@ export declare function fromJson<Desc extends DescMessage>(messageDesc: Desc, js
45
45
  * If a message field is already present, it will be merged with the
46
46
  * new data.
47
47
  */
48
- export declare function mergeFromJson<Desc extends DescMessage>(messageDesc: Desc, target: MessageShape<Desc>, json: JsonValue, options?: Partial<JsonReadOptions>): void;
48
+ export declare function mergeFromJson<Desc extends DescMessage>(messageDesc: Desc, target: MessageShape<Desc>, json: JsonValue, options?: Partial<JsonReadOptions>): MessageShape<Desc>;
@@ -49,7 +49,7 @@ exports.fromJsonString = fromJsonString;
49
49
  * new data.
50
50
  */
51
51
  function mergeFromJsonString(messageDesc, target, json, options) {
52
- mergeFromJson(messageDesc, target, parseJsonString(json, messageDesc.typeName), options);
52
+ return mergeFromJson(messageDesc, target, parseJsonString(json, messageDesc.typeName), options);
53
53
  }
54
54
  exports.mergeFromJsonString = mergeFromJsonString;
55
55
  /**
@@ -94,6 +94,7 @@ function mergeFromJson(messageDesc, target, json, options) {
94
94
  }
95
95
  throw e;
96
96
  }
97
+ return target;
97
98
  }
98
99
  exports.mergeFromJson = mergeFromJson;
99
100
  function readMessage(msg, json, opts) {
@@ -153,17 +154,18 @@ function readField(msg, field, json, opts) {
153
154
  readMessageField(msg, field, json, opts);
154
155
  break;
155
156
  case "list":
156
- readListField(msg, field, json, opts);
157
+ readListField(msg.get(field), json, opts);
157
158
  break;
158
159
  case "map":
159
- readMapField(msg, field, json, opts);
160
+ readMapField(msg.get(field), json, opts);
160
161
  break;
161
162
  }
162
163
  }
163
- function readMapField(msg, field, json, opts) {
164
+ function readMapField(map, json, opts) {
164
165
  if (json === null) {
165
166
  return;
166
167
  }
168
+ const field = map.field();
167
169
  if (typeof json != "object" || Array.isArray(json)) {
168
170
  throw new error_js_1.FieldError(field, "expected object, got " + (0, reflect_check_js_1.formatVal)(json));
169
171
  }
@@ -171,45 +173,37 @@ function readMapField(msg, field, json, opts) {
171
173
  if (jsonMapValue === null) {
172
174
  throw new error_js_1.FieldError(field, "map value must not be null");
173
175
  }
174
- const key = mapKeyFromJson(field.mapKey, jsonMapKey);
176
+ let value;
175
177
  switch (field.mapKind) {
176
178
  case "message":
177
179
  const msgValue = (0, reflect_js_1.reflect)(field.message);
178
180
  readMessage(msgValue, jsonMapValue, opts);
179
- // TODO fix types
180
- // @ts-expect-error TODO
181
- const err = msg.setMapEntry(field, key, msgValue);
182
- if (err) {
183
- throw err;
184
- }
181
+ value = msgValue;
185
182
  break;
186
183
  case "enum":
187
- const enumValue = readEnum(field.enum, jsonMapValue, opts.ignoreUnknownFields, true);
188
- if (enumValue !== tokenIgnoredUnknownEnum) {
189
- // TODO fix types
190
- // @ts-expect-error TODO
191
- const err = msg.setMapEntry(field, key, enumValue);
192
- if (err) {
193
- throw err;
194
- }
184
+ value = readEnum(field.enum, jsonMapValue, opts.ignoreUnknownFields, true);
185
+ if (value === tokenIgnoredUnknownEnum) {
186
+ return;
195
187
  }
196
188
  break;
197
189
  case "scalar":
198
- const err2 = msg.setMapEntry(field,
199
- // TODO fix types
200
- // @ts-expect-error TODO
201
- key, scalarFromJson(field, jsonMapValue, true));
202
- if (err2) {
203
- throw err2;
204
- }
190
+ value = scalarFromJson(field, jsonMapValue, true);
205
191
  break;
206
192
  }
193
+ const key = mapKeyFromJson(field.mapKey, jsonMapKey);
194
+ // TODO fix types
195
+ // @ts-expect-error TODO
196
+ const err = map.set(key, value);
197
+ if (err) {
198
+ throw err;
199
+ }
207
200
  }
208
201
  }
209
- function readListField(msg, field, json, opts) {
202
+ function readListField(list, json, opts) {
210
203
  if (json === null) {
211
204
  return;
212
205
  }
206
+ const field = list.field();
213
207
  if (!Array.isArray(json)) {
214
208
  throw new error_js_1.FieldError(field, "expected Array, got " + (0, reflect_check_js_1.formatVal)(json));
215
209
  }
@@ -221,16 +215,16 @@ function readListField(msg, field, json, opts) {
221
215
  case "message":
222
216
  const msgValue = (0, reflect_js_1.reflect)(field.message);
223
217
  readMessage(msgValue, jsonItem, opts);
224
- msg.addListItem(field, msgValue);
218
+ list.add(msgValue);
225
219
  break;
226
220
  case "enum":
227
221
  const enumValue = readEnum(field.enum, jsonItem, opts.ignoreUnknownFields, true);
228
222
  if (enumValue !== tokenIgnoredUnknownEnum) {
229
- msg.addListItem(field, enumValue);
223
+ list.add(enumValue);
230
224
  }
231
225
  break;
232
226
  case "scalar":
233
- const err = msg.addListItem(field, scalarFromJson(field, jsonItem, true));
227
+ const err = list.add(scalarFromJson(field, jsonItem, true));
234
228
  if (err) {
235
229
  throw err;
236
230
  }
@@ -15,7 +15,6 @@
15
15
  Object.defineProperty(exports, "__esModule", { value: true });
16
16
  exports.isReflectMessage = exports.isReflectMap = exports.isReflectList = exports.isOneofADT = exports.isObject = void 0;
17
17
  const unsafe_js_1 = require("./unsafe.js");
18
- const is_message_js_1 = require("../is-message.js");
19
18
  function isObject(arg) {
20
19
  return arg !== null && typeof arg == "object" && !Array.isArray(arg);
21
20
  }
@@ -71,8 +70,9 @@ exports.isReflectMap = isReflectMap;
71
70
  function isReflectMessage(arg, messageDesc) {
72
71
  return (isObject(arg) &&
73
72
  unsafe_js_1.unsafeLocal in arg &&
74
- "message" in arg &&
75
- (0, is_message_js_1.isMessage)(arg.message) &&
76
- (messageDesc === undefined || arg.message.$typeName == messageDesc.typeName));
73
+ "desc" in arg &&
74
+ isObject(arg.desc) &&
75
+ arg.desc.kind === "message" &&
76
+ (messageDesc === undefined || arg.desc.typeName == messageDesc.typeName));
77
77
  }
78
78
  exports.isReflectMessage = isReflectMessage;
@@ -109,18 +109,6 @@ export interface ReflectMessage {
109
109
  * a valid value. To reset a field, use clear().
110
110
  */
111
111
  set<Field extends DescField>(field: Field, value: ReflectSetValue<Field>): FieldError | undefined;
112
- /**
113
- * Add an item to a list field.
114
- */
115
- addListItem<Field extends DescField & {
116
- fieldKind: "list";
117
- }>(field: Field, value: ReflectAddListItemValue<Field>): FieldError | undefined;
118
- /**
119
- * Set a map entry.
120
- */
121
- setMapEntry<Field extends DescField & {
122
- fieldKind: "map";
123
- }>(field: Field, key: MapEntryKey, value: ReflectSetMapEntryValue<Field>): FieldError | undefined;
124
112
  /**
125
113
  * Returns the unknown fields of the message.
126
114
  */
@@ -255,30 +243,4 @@ export type ReflectSetValue<Field extends DescField = DescField> = (Field extend
255
243
  fieldKind: "scalar";
256
244
  scalar: infer T;
257
245
  } ? ScalarValue<T> : never);
258
- /**
259
- * The type of the "value" argument of ReflectMessage.addListItem()
260
- */
261
- export type ReflectAddListItemValue<Field extends DescField & {
262
- fieldKind: "list";
263
- }> = (Field extends {
264
- listKind: "scalar";
265
- scalar: infer T;
266
- } ? ScalarValue<T> : Field extends {
267
- listKind: "enum";
268
- } ? enumVal : Field extends {
269
- listKind: "message";
270
- } ? ReflectMessage : never);
271
- /**
272
- * The type of the "value" argument of ReflectMessage.setMapEntry()
273
- */
274
- export type ReflectSetMapEntryValue<Field extends DescField & {
275
- fieldKind: "map";
276
- }> = (Field extends {
277
- mapKind: "enum";
278
- } ? enumVal : Field extends {
279
- mapKind: "message";
280
- } ? ReflectMessage : Field extends {
281
- mapKind: "scalar";
282
- scalar: infer T;
283
- } ? ScalarValue<T> : never);
284
246
  export {};
@@ -42,6 +42,8 @@ class ReflectMessageImpl {
42
42
  constructor(messageDesc, message,
43
43
  // TODO either remove this option, or support it in reflect-list and reflect-map as well
44
44
  check = true) {
45
+ this.lists = new Map();
46
+ this.maps = new Map();
45
47
  this.check = check;
46
48
  this.desc = messageDesc;
47
49
  this.message = this[unsafe_js_1.unsafeLocal] = message !== null && message !== void 0 ? message : (0, create_js_1.create)(messageDesc);
@@ -72,11 +74,19 @@ class ReflectMessageImpl {
72
74
  let value = (0, unsafe_js_1.unsafeGet)(this.message, field);
73
75
  switch (field.fieldKind) {
74
76
  case "list":
75
- return new ReflectListImpl(field, value, this.check);
77
+ // eslint-disable-next-line no-case-declarations
78
+ let list = this.lists.get(field);
79
+ if (!list || list[unsafe_js_1.unsafeLocal] !== value) {
80
+ this.lists.set(field, (list = new ReflectListImpl(field, value, this.check)));
81
+ }
82
+ return list;
76
83
  case "map":
77
- // TODO fix types
78
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
79
- return reflectMap(field, value, this.check); // eslint-disable-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-return
84
+ // eslint-disable-next-line no-case-declarations
85
+ let map = this.maps.get(field);
86
+ if (!map || map[unsafe_js_1.unsafeLocal] !== value) {
87
+ this.maps.set(field, (map = new ReflectMapImpl(field, value, this.check)));
88
+ }
89
+ return map;
80
90
  case "message":
81
91
  if (value !== undefined &&
82
92
  !field.oneof &&
@@ -117,30 +127,6 @@ class ReflectMessageImpl {
117
127
  (0, unsafe_js_1.unsafeSet)(this.message, field, local);
118
128
  return undefined;
119
129
  }
120
- addListItem(field, value) {
121
- assertOwn(this.message, field);
122
- assertKind(field, "list");
123
- if (this.check) {
124
- if ((0, reflect_check_js_1.checkListItem)(field, 0, value)) {
125
- const arr = (0, unsafe_js_1.unsafeGet)(this.message, field);
126
- return (0, reflect_check_js_1.checkListItem)(field, arr.length, value);
127
- }
128
- }
129
- (0, unsafe_js_1.unsafeAddListItem)(this.message, field, listItemToLocal(field, value));
130
- return undefined;
131
- }
132
- setMapEntry(field, key, value) {
133
- assertOwn(this.message, field);
134
- assertKind(field, "map");
135
- if (this.check) {
136
- const err = (0, reflect_check_js_1.checkMapEntry)(field, key, value);
137
- if (err) {
138
- return err;
139
- }
140
- }
141
- (0, unsafe_js_1.unsafeSetMapEntry)(this.message, field, mapKeyToLocal(key), mapValueToLocal(field, value));
142
- return undefined;
143
- }
144
130
  getUnknown() {
145
131
  return this.message.$unknown;
146
132
  }
@@ -148,11 +134,6 @@ class ReflectMessageImpl {
148
134
  this.message.$unknown = value;
149
135
  }
150
136
  }
151
- function assertKind(field, kind) {
152
- if (field.fieldKind != kind) {
153
- throw new error_js_1.FieldError(field, `${field.toString()} is ${field.fieldKind}`, "ForeignFieldError");
154
- }
155
- }
156
137
  function assertOwn(owner, member) {
157
138
  if (member.parent.typeName !== owner.$typeName) {
158
139
  throw new error_js_1.FieldError(member, `cannot use ${member.toString()} with message ${owner.$typeName}`, "ForeignFieldError");
@@ -40,19 +40,3 @@ export declare function unsafeSet(target: Record<string, unknown>, field: DescFi
40
40
  */
41
41
  export declare function unsafeClear(target: Record<string, any>, // eslint-disable-line @typescript-eslint/no-explicit-any -- `any` is the best choice for dynamic access
42
42
  field: DescField): void;
43
- /**
44
- * Add an item to a list field.
45
- *
46
- * @private
47
- */
48
- export declare function unsafeAddListItem(target: Record<string, unknown>, field: DescField & {
49
- fieldKind: "list";
50
- }, value: unknown): void;
51
- /**
52
- * Set a map entry.
53
- *
54
- * @private
55
- */
56
- export declare function unsafeSetMapEntry(target: Record<string, unknown>, field: DescField & {
57
- fieldKind: "map";
58
- }, key: string | number, value: unknown): void;
@@ -13,7 +13,7 @@
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.unsafeSetMapEntry = exports.unsafeAddListItem = exports.unsafeClear = exports.unsafeSet = exports.unsafeGet = exports.unsafeIsSetExplicit = exports.unsafeIsSet = exports.unsafeOneofCase = exports.unsafeLocal = void 0;
16
+ exports.unsafeClear = exports.unsafeSet = exports.unsafeGet = exports.unsafeIsSetExplicit = exports.unsafeIsSet = exports.unsafeOneofCase = exports.unsafeLocal = void 0;
17
17
  const scalar_js_1 = require("./scalar.js");
18
18
  // bootstrap-inject google.protobuf.FeatureSet.FieldPresence.IMPLICIT: const $name: FeatureSet_FieldPresence.$localName = $number;
19
19
  const IMPLICIT = 2;
@@ -146,21 +146,3 @@ field) {
146
146
  }
147
147
  }
148
148
  exports.unsafeClear = unsafeClear;
149
- /**
150
- * Add an item to a list field.
151
- *
152
- * @private
153
- */
154
- function unsafeAddListItem(target, field, value) {
155
- target[field.localName].push(value);
156
- }
157
- exports.unsafeAddListItem = unsafeAddListItem;
158
- /**
159
- * Set a map entry.
160
- *
161
- * @private
162
- */
163
- function unsafeSetMapEntry(target, field, key, value) {
164
- target[field.localName][key] = value;
165
- }
166
- exports.unsafeSetMapEntry = unsafeSetMapEntry;
@@ -462,29 +462,50 @@ class BinaryReader {
462
462
  }
463
463
  exports.BinaryReader = BinaryReader;
464
464
  /**
465
- * Assert a valid signed protobuf 32-bit integer.
465
+ * Assert a valid signed protobuf 32-bit integer as a number or string.
466
466
  */
467
467
  function assertInt32(arg) {
468
- if (typeof arg !== "number")
468
+ if (typeof arg == "string") {
469
+ arg = Number(arg);
470
+ }
471
+ else if (typeof arg != "number") {
469
472
  throw new Error("invalid int32: " + typeof arg);
470
- if (!Number.isInteger(arg) || arg > exports.INT32_MAX || arg < exports.INT32_MIN)
473
+ }
474
+ if (!Number.isInteger(arg) ||
475
+ arg > exports.INT32_MAX ||
476
+ arg < exports.INT32_MIN)
471
477
  throw new Error("invalid int32: " + arg);
472
478
  }
473
479
  /**
474
- * Assert a valid unsigned protobuf 32-bit integer.
480
+ * Assert a valid unsigned protobuf 32-bit integer as a number or string.
475
481
  */
476
482
  function assertUInt32(arg) {
477
- if (typeof arg !== "number")
483
+ if (typeof arg == "string") {
484
+ arg = Number(arg);
485
+ }
486
+ else if (typeof arg != "number") {
478
487
  throw new Error("invalid uint32: " + typeof arg);
479
- if (!Number.isInteger(arg) || arg > exports.UINT32_MAX || arg < 0)
488
+ }
489
+ if (!Number.isInteger(arg) ||
490
+ arg > exports.UINT32_MAX ||
491
+ arg < 0)
480
492
  throw new Error("invalid uint32: " + arg);
481
493
  }
482
494
  /**
483
- * Assert a valid protobuf float value.
495
+ * Assert a valid protobuf float value as a number or string.
484
496
  */
485
497
  function assertFloat32(arg) {
486
- if (typeof arg !== "number")
498
+ if (typeof arg == "string") {
499
+ const o = arg;
500
+ arg = Number(arg);
501
+ if (isNaN(arg) && o !== "NaN") {
502
+ throw new Error("invalid float32: " + o);
503
+ }
504
+ }
505
+ else if (typeof arg != "number") {
487
506
  throw new Error("invalid float32: " + typeof arg);
488
- if (Number.isFinite(arg) && (arg > exports.FLOAT32_MAX || arg < exports.FLOAT32_MIN))
507
+ }
508
+ if (Number.isFinite(arg) &&
509
+ (arg > exports.FLOAT32_MAX || arg < exports.FLOAT32_MIN))
489
510
  throw new Error("invalid float32: " + arg);
490
511
  }
@@ -35,4 +35,4 @@ export declare function anyUnpack<Desc extends DescMessage>(any: Any, messageDes
35
35
  /**
36
36
  * Same as anyUnpack but unpacks into the target message.
37
37
  */
38
- export declare function anyUnpackTo<Desc extends DescMessage>(any: Any, messageDesc: Desc, message: MessageShape<Desc>): void;
38
+ export declare function anyUnpackTo<Desc extends DescMessage>(any: Any, messageDesc: Desc, message: MessageShape<Desc>): MessageShape<Desc> | undefined;
package/dist/esm/clone.js CHANGED
@@ -36,18 +36,21 @@ function cloneReflect(i) {
36
36
  break;
37
37
  }
38
38
  case "list":
39
+ // eslint-disable-next-line no-case-declarations
40
+ const list = o.get(f);
39
41
  for (const item of i.get(f)) {
40
- // TODO fix type error
41
- // @ts-expect-error TODO
42
- const err = o.addListItem(f, cloneSingular(f, item));
42
+ const err = list.add(cloneSingular(f, item));
43
43
  if (err) {
44
44
  throw err;
45
45
  }
46
46
  }
47
47
  break;
48
48
  case "map":
49
+ // eslint-disable-next-line no-case-declarations
50
+ const map = o.get(f);
49
51
  for (const entry of i.get(f).entries()) {
50
- const err = o.setMapEntry(f, entry[0], cloneSingular(f, entry[1]));
52
+ // @ts-expect-error TODO fix type error
53
+ const err = map.set(entry[0], cloneSingular(f, entry[1]));
51
54
  if (err) {
52
55
  throw err;
53
56
  }
@@ -27,7 +27,7 @@ export declare function fromBinary<Desc extends DescMessage>(messageDesc: Desc,
27
27
  * If a message field is already present, it will be merged with the
28
28
  * new data.
29
29
  */
30
- export declare function mergeFromBinary<Desc extends DescMessage>(messageDesc: Desc, target: MessageShape<Desc>, bytes: Uint8Array, options?: Partial<BinaryReadOptions>): void;
30
+ export declare function mergeFromBinary<Desc extends DescMessage>(messageDesc: Desc, target: MessageShape<Desc>, bytes: Uint8Array, options?: Partial<BinaryReadOptions>): MessageShape<Desc>;
31
31
  /**
32
32
  * @private
33
33
  */
@@ -41,6 +41,7 @@ export function fromBinary(messageDesc, bytes, options) {
41
41
  */
42
42
  export function mergeFromBinary(messageDesc, target, bytes, options) {
43
43
  readMessage(reflect(messageDesc, target), new BinaryReader(bytes), makeReadOptions(options), false, bytes.byteLength);
44
+ return target;
44
45
  }
45
46
  /**
46
47
  * If `delimited` is false, read the length given in `lengthOrDelimitedFieldNo`.
@@ -94,15 +95,16 @@ export function readField(message, reader, field, wireType, options) {
94
95
  message.set(field, readMessageField(reader, options, field, message.get(field)));
95
96
  break;
96
97
  case "list":
97
- readListField(message, reader, options, field, wireType);
98
+ readListField(reader, wireType, message.get(field), options);
98
99
  break;
99
100
  case "map":
100
- readMapEntry(message, field, reader, options);
101
+ readMapEntry(reader, message.get(field), options);
101
102
  break;
102
103
  }
103
104
  }
104
105
  // Read a map field, expecting key field = 1, value field = 2
105
- function readMapEntry(message, field, reader, options) {
106
+ function readMapEntry(reader, map, options) {
107
+ const field = map.field();
106
108
  let key, val;
107
109
  const end = reader.pos + reader.uint32();
108
110
  while (reader.pos < end) {
@@ -142,12 +144,13 @@ function readMapEntry(message, field, reader, options) {
142
144
  break;
143
145
  }
144
146
  }
145
- message.setMapEntry(field, key, val);
147
+ map.set(key, val);
146
148
  }
147
- function readListField(message, reader, options, field, wireType) {
149
+ function readListField(reader, wireType, list, options) {
148
150
  var _a;
151
+ const field = list.field();
149
152
  if (field.listKind === "message") {
150
- message.addListItem(field, readMessageField(reader, options, field));
153
+ list.add(readMessageField(reader, options, field));
151
154
  return;
152
155
  }
153
156
  const scalarType = (_a = field.scalar) !== null && _a !== void 0 ? _a : ScalarType.INT32;
@@ -155,12 +158,12 @@ function readListField(message, reader, options, field, wireType) {
155
158
  scalarType != ScalarType.STRING &&
156
159
  scalarType != ScalarType.BYTES;
157
160
  if (!packed) {
158
- message.addListItem(field, readScalar(reader, scalarType));
161
+ list.add(readScalar(reader, scalarType));
159
162
  return;
160
163
  }
161
164
  const e = reader.uint32() + reader.pos;
162
165
  while (reader.pos < e) {
163
- message.addListItem(field, readScalar(reader, scalarType));
166
+ list.add(readScalar(reader, scalarType));
164
167
  }
165
168
  }
166
169
  function readMessageField(reader, options, field, mergeMessage) {
@@ -31,7 +31,7 @@ export declare function fromJsonString<Desc extends DescMessage>(messageDesc: De
31
31
  * If a message field is already present, it will be merged with the
32
32
  * new data.
33
33
  */
34
- export declare function mergeFromJsonString<Desc extends DescMessage>(messageDesc: Desc, target: MessageShape<Desc>, json: string, options?: Partial<JsonReadOptions>): void;
34
+ export declare function mergeFromJsonString<Desc extends DescMessage>(messageDesc: Desc, target: MessageShape<Desc>, json: string, options?: Partial<JsonReadOptions>): MessageShape<Desc>;
35
35
  /**
36
36
  * Parse a message from a JSON value.
37
37
  */
@@ -45,4 +45,4 @@ export declare function fromJson<Desc extends DescMessage>(messageDesc: Desc, js
45
45
  * If a message field is already present, it will be merged with the
46
46
  * new data.
47
47
  */
48
- export declare function mergeFromJson<Desc extends DescMessage>(messageDesc: Desc, target: MessageShape<Desc>, json: JsonValue, options?: Partial<JsonReadOptions>): void;
48
+ export declare function mergeFromJson<Desc extends DescMessage>(messageDesc: Desc, target: MessageShape<Desc>, json: JsonValue, options?: Partial<JsonReadOptions>): MessageShape<Desc>;
@@ -45,7 +45,7 @@ export function fromJsonString(messageDesc, json, options) {
45
45
  * new data.
46
46
  */
47
47
  export function mergeFromJsonString(messageDesc, target, json, options) {
48
- mergeFromJson(messageDesc, target, parseJsonString(json, messageDesc.typeName), options);
48
+ return mergeFromJson(messageDesc, target, parseJsonString(json, messageDesc.typeName), options);
49
49
  }
50
50
  /**
51
51
  * Parse a message from a JSON value.
@@ -88,6 +88,7 @@ export function mergeFromJson(messageDesc, target, json, options) {
88
88
  }
89
89
  throw e;
90
90
  }
91
+ return target;
91
92
  }
92
93
  function readMessage(msg, json, opts) {
93
94
  var _a;
@@ -146,17 +147,18 @@ function readField(msg, field, json, opts) {
146
147
  readMessageField(msg, field, json, opts);
147
148
  break;
148
149
  case "list":
149
- readListField(msg, field, json, opts);
150
+ readListField(msg.get(field), json, opts);
150
151
  break;
151
152
  case "map":
152
- readMapField(msg, field, json, opts);
153
+ readMapField(msg.get(field), json, opts);
153
154
  break;
154
155
  }
155
156
  }
156
- function readMapField(msg, field, json, opts) {
157
+ function readMapField(map, json, opts) {
157
158
  if (json === null) {
158
159
  return;
159
160
  }
161
+ const field = map.field();
160
162
  if (typeof json != "object" || Array.isArray(json)) {
161
163
  throw new FieldError(field, "expected object, got " + formatVal(json));
162
164
  }
@@ -164,45 +166,37 @@ function readMapField(msg, field, json, opts) {
164
166
  if (jsonMapValue === null) {
165
167
  throw new FieldError(field, "map value must not be null");
166
168
  }
167
- const key = mapKeyFromJson(field.mapKey, jsonMapKey);
169
+ let value;
168
170
  switch (field.mapKind) {
169
171
  case "message":
170
172
  const msgValue = reflect(field.message);
171
173
  readMessage(msgValue, jsonMapValue, opts);
172
- // TODO fix types
173
- // @ts-expect-error TODO
174
- const err = msg.setMapEntry(field, key, msgValue);
175
- if (err) {
176
- throw err;
177
- }
174
+ value = msgValue;
178
175
  break;
179
176
  case "enum":
180
- const enumValue = readEnum(field.enum, jsonMapValue, opts.ignoreUnknownFields, true);
181
- if (enumValue !== tokenIgnoredUnknownEnum) {
182
- // TODO fix types
183
- // @ts-expect-error TODO
184
- const err = msg.setMapEntry(field, key, enumValue);
185
- if (err) {
186
- throw err;
187
- }
177
+ value = readEnum(field.enum, jsonMapValue, opts.ignoreUnknownFields, true);
178
+ if (value === tokenIgnoredUnknownEnum) {
179
+ return;
188
180
  }
189
181
  break;
190
182
  case "scalar":
191
- const err2 = msg.setMapEntry(field,
192
- // TODO fix types
193
- // @ts-expect-error TODO
194
- key, scalarFromJson(field, jsonMapValue, true));
195
- if (err2) {
196
- throw err2;
197
- }
183
+ value = scalarFromJson(field, jsonMapValue, true);
198
184
  break;
199
185
  }
186
+ const key = mapKeyFromJson(field.mapKey, jsonMapKey);
187
+ // TODO fix types
188
+ // @ts-expect-error TODO
189
+ const err = map.set(key, value);
190
+ if (err) {
191
+ throw err;
192
+ }
200
193
  }
201
194
  }
202
- function readListField(msg, field, json, opts) {
195
+ function readListField(list, json, opts) {
203
196
  if (json === null) {
204
197
  return;
205
198
  }
199
+ const field = list.field();
206
200
  if (!Array.isArray(json)) {
207
201
  throw new FieldError(field, "expected Array, got " + formatVal(json));
208
202
  }
@@ -214,16 +208,16 @@ function readListField(msg, field, json, opts) {
214
208
  case "message":
215
209
  const msgValue = reflect(field.message);
216
210
  readMessage(msgValue, jsonItem, opts);
217
- msg.addListItem(field, msgValue);
211
+ list.add(msgValue);
218
212
  break;
219
213
  case "enum":
220
214
  const enumValue = readEnum(field.enum, jsonItem, opts.ignoreUnknownFields, true);
221
215
  if (enumValue !== tokenIgnoredUnknownEnum) {
222
- msg.addListItem(field, enumValue);
216
+ list.add(enumValue);
223
217
  }
224
218
  break;
225
219
  case "scalar":
226
- const err = msg.addListItem(field, scalarFromJson(field, jsonItem, true));
220
+ const err = list.add(scalarFromJson(field, jsonItem, true));
227
221
  if (err) {
228
222
  throw err;
229
223
  }
@@ -12,7 +12,6 @@
12
12
  // See the License for the specific language governing permissions and
13
13
  // limitations under the License.
14
14
  import { unsafeLocal } from "./unsafe.js";
15
- import { isMessage } from "../is-message.js";
16
15
  export function isObject(arg) {
17
16
  return arg !== null && typeof arg == "object" && !Array.isArray(arg);
18
17
  }
@@ -64,7 +63,8 @@ export function isReflectMap(arg, field) {
64
63
  export function isReflectMessage(arg, messageDesc) {
65
64
  return (isObject(arg) &&
66
65
  unsafeLocal in arg &&
67
- "message" in arg &&
68
- isMessage(arg.message) &&
69
- (messageDesc === undefined || arg.message.$typeName == messageDesc.typeName));
66
+ "desc" in arg &&
67
+ isObject(arg.desc) &&
68
+ arg.desc.kind === "message" &&
69
+ (messageDesc === undefined || arg.desc.typeName == messageDesc.typeName));
70
70
  }
@@ -109,18 +109,6 @@ export interface ReflectMessage {
109
109
  * a valid value. To reset a field, use clear().
110
110
  */
111
111
  set<Field extends DescField>(field: Field, value: ReflectSetValue<Field>): FieldError | undefined;
112
- /**
113
- * Add an item to a list field.
114
- */
115
- addListItem<Field extends DescField & {
116
- fieldKind: "list";
117
- }>(field: Field, value: ReflectAddListItemValue<Field>): FieldError | undefined;
118
- /**
119
- * Set a map entry.
120
- */
121
- setMapEntry<Field extends DescField & {
122
- fieldKind: "map";
123
- }>(field: Field, key: MapEntryKey, value: ReflectSetMapEntryValue<Field>): FieldError | undefined;
124
112
  /**
125
113
  * Returns the unknown fields of the message.
126
114
  */
@@ -255,30 +243,4 @@ export type ReflectSetValue<Field extends DescField = DescField> = (Field extend
255
243
  fieldKind: "scalar";
256
244
  scalar: infer T;
257
245
  } ? ScalarValue<T> : never);
258
- /**
259
- * The type of the "value" argument of ReflectMessage.addListItem()
260
- */
261
- export type ReflectAddListItemValue<Field extends DescField & {
262
- fieldKind: "list";
263
- }> = (Field extends {
264
- listKind: "scalar";
265
- scalar: infer T;
266
- } ? ScalarValue<T> : Field extends {
267
- listKind: "enum";
268
- } ? enumVal : Field extends {
269
- listKind: "message";
270
- } ? ReflectMessage : never);
271
- /**
272
- * The type of the "value" argument of ReflectMessage.setMapEntry()
273
- */
274
- export type ReflectSetMapEntryValue<Field extends DescField & {
275
- fieldKind: "map";
276
- }> = (Field extends {
277
- mapKind: "enum";
278
- } ? enumVal : Field extends {
279
- mapKind: "message";
280
- } ? ReflectMessage : Field extends {
281
- mapKind: "scalar";
282
- scalar: infer T;
283
- } ? ScalarValue<T> : never);
284
246
  export {};
@@ -14,7 +14,7 @@
14
14
  import { ScalarType, } from "../descriptors.js";
15
15
  import { checkField, checkListItem, checkMapEntry } from "./reflect-check.js";
16
16
  import { FieldError } from "./error.js";
17
- import { unsafeAddListItem, unsafeClear, unsafeGet, unsafeIsSet, unsafeLocal, unsafeOneofCase, unsafeSet, unsafeSetMapEntry, } from "./unsafe.js";
17
+ import { unsafeClear, unsafeGet, unsafeIsSet, unsafeLocal, unsafeOneofCase, unsafeSet, } from "./unsafe.js";
18
18
  import { create } from "../create.js";
19
19
  import { isWrapper, isWrapperDesc } from "../wkt/wrappers.js";
20
20
  import { scalarZeroValue } from "./scalar.js";
@@ -38,6 +38,8 @@ class ReflectMessageImpl {
38
38
  constructor(messageDesc, message,
39
39
  // TODO either remove this option, or support it in reflect-list and reflect-map as well
40
40
  check = true) {
41
+ this.lists = new Map();
42
+ this.maps = new Map();
41
43
  this.check = check;
42
44
  this.desc = messageDesc;
43
45
  this.message = this[unsafeLocal] = message !== null && message !== void 0 ? message : create(messageDesc);
@@ -68,11 +70,19 @@ class ReflectMessageImpl {
68
70
  let value = unsafeGet(this.message, field);
69
71
  switch (field.fieldKind) {
70
72
  case "list":
71
- return new ReflectListImpl(field, value, this.check);
73
+ // eslint-disable-next-line no-case-declarations
74
+ let list = this.lists.get(field);
75
+ if (!list || list[unsafeLocal] !== value) {
76
+ this.lists.set(field, (list = new ReflectListImpl(field, value, this.check)));
77
+ }
78
+ return list;
72
79
  case "map":
73
- // TODO fix types
74
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
75
- return reflectMap(field, value, this.check); // eslint-disable-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-return
80
+ // eslint-disable-next-line no-case-declarations
81
+ let map = this.maps.get(field);
82
+ if (!map || map[unsafeLocal] !== value) {
83
+ this.maps.set(field, (map = new ReflectMapImpl(field, value, this.check)));
84
+ }
85
+ return map;
76
86
  case "message":
77
87
  if (value !== undefined &&
78
88
  !field.oneof &&
@@ -113,30 +123,6 @@ class ReflectMessageImpl {
113
123
  unsafeSet(this.message, field, local);
114
124
  return undefined;
115
125
  }
116
- addListItem(field, value) {
117
- assertOwn(this.message, field);
118
- assertKind(field, "list");
119
- if (this.check) {
120
- if (checkListItem(field, 0, value)) {
121
- const arr = unsafeGet(this.message, field);
122
- return checkListItem(field, arr.length, value);
123
- }
124
- }
125
- unsafeAddListItem(this.message, field, listItemToLocal(field, value));
126
- return undefined;
127
- }
128
- setMapEntry(field, key, value) {
129
- assertOwn(this.message, field);
130
- assertKind(field, "map");
131
- if (this.check) {
132
- const err = checkMapEntry(field, key, value);
133
- if (err) {
134
- return err;
135
- }
136
- }
137
- unsafeSetMapEntry(this.message, field, mapKeyToLocal(key), mapValueToLocal(field, value));
138
- return undefined;
139
- }
140
126
  getUnknown() {
141
127
  return this.message.$unknown;
142
128
  }
@@ -144,11 +130,6 @@ class ReflectMessageImpl {
144
130
  this.message.$unknown = value;
145
131
  }
146
132
  }
147
- function assertKind(field, kind) {
148
- if (field.fieldKind != kind) {
149
- throw new FieldError(field, `${field.toString()} is ${field.fieldKind}`, "ForeignFieldError");
150
- }
151
- }
152
133
  function assertOwn(owner, member) {
153
134
  if (member.parent.typeName !== owner.$typeName) {
154
135
  throw new FieldError(member, `cannot use ${member.toString()} with message ${owner.$typeName}`, "ForeignFieldError");
@@ -40,19 +40,3 @@ export declare function unsafeSet(target: Record<string, unknown>, field: DescFi
40
40
  */
41
41
  export declare function unsafeClear(target: Record<string, any>, // eslint-disable-line @typescript-eslint/no-explicit-any -- `any` is the best choice for dynamic access
42
42
  field: DescField): void;
43
- /**
44
- * Add an item to a list field.
45
- *
46
- * @private
47
- */
48
- export declare function unsafeAddListItem(target: Record<string, unknown>, field: DescField & {
49
- fieldKind: "list";
50
- }, value: unknown): void;
51
- /**
52
- * Set a map entry.
53
- *
54
- * @private
55
- */
56
- export declare function unsafeSetMapEntry(target: Record<string, unknown>, field: DescField & {
57
- fieldKind: "map";
58
- }, key: string | number, value: unknown): void;
@@ -137,19 +137,3 @@ field) {
137
137
  }
138
138
  }
139
139
  }
140
- /**
141
- * Add an item to a list field.
142
- *
143
- * @private
144
- */
145
- export function unsafeAddListItem(target, field, value) {
146
- target[field.localName].push(value);
147
- }
148
- /**
149
- * Set a map entry.
150
- *
151
- * @private
152
- */
153
- export function unsafeSetMapEntry(target, field, key, value) {
154
- target[field.localName][key] = value;
155
- }
@@ -457,29 +457,50 @@ export class BinaryReader {
457
457
  }
458
458
  }
459
459
  /**
460
- * Assert a valid signed protobuf 32-bit integer.
460
+ * Assert a valid signed protobuf 32-bit integer as a number or string.
461
461
  */
462
462
  function assertInt32(arg) {
463
- if (typeof arg !== "number")
463
+ if (typeof arg == "string") {
464
+ arg = Number(arg);
465
+ }
466
+ else if (typeof arg != "number") {
464
467
  throw new Error("invalid int32: " + typeof arg);
465
- if (!Number.isInteger(arg) || arg > INT32_MAX || arg < INT32_MIN)
468
+ }
469
+ if (!Number.isInteger(arg) ||
470
+ arg > INT32_MAX ||
471
+ arg < INT32_MIN)
466
472
  throw new Error("invalid int32: " + arg);
467
473
  }
468
474
  /**
469
- * Assert a valid unsigned protobuf 32-bit integer.
475
+ * Assert a valid unsigned protobuf 32-bit integer as a number or string.
470
476
  */
471
477
  function assertUInt32(arg) {
472
- if (typeof arg !== "number")
478
+ if (typeof arg == "string") {
479
+ arg = Number(arg);
480
+ }
481
+ else if (typeof arg != "number") {
473
482
  throw new Error("invalid uint32: " + typeof arg);
474
- if (!Number.isInteger(arg) || arg > UINT32_MAX || arg < 0)
483
+ }
484
+ if (!Number.isInteger(arg) ||
485
+ arg > UINT32_MAX ||
486
+ arg < 0)
475
487
  throw new Error("invalid uint32: " + arg);
476
488
  }
477
489
  /**
478
- * Assert a valid protobuf float value.
490
+ * Assert a valid protobuf float value as a number or string.
479
491
  */
480
492
  function assertFloat32(arg) {
481
- if (typeof arg !== "number")
493
+ if (typeof arg == "string") {
494
+ const o = arg;
495
+ arg = Number(arg);
496
+ if (isNaN(arg) && o !== "NaN") {
497
+ throw new Error("invalid float32: " + o);
498
+ }
499
+ }
500
+ else if (typeof arg != "number") {
482
501
  throw new Error("invalid float32: " + typeof arg);
483
- if (Number.isFinite(arg) && (arg > FLOAT32_MAX || arg < FLOAT32_MIN))
502
+ }
503
+ if (Number.isFinite(arg) &&
504
+ (arg > FLOAT32_MAX || arg < FLOAT32_MIN))
484
505
  throw new Error("invalid float32: " + arg);
485
506
  }
@@ -35,4 +35,4 @@ export declare function anyUnpack<Desc extends DescMessage>(any: Any, messageDes
35
35
  /**
36
36
  * Same as anyUnpack but unpacks into the target message.
37
37
  */
38
- export declare function anyUnpackTo<Desc extends DescMessage>(any: Any, messageDesc: Desc, message: MessageShape<Desc>): void;
38
+ export declare function anyUnpackTo<Desc extends DescMessage>(any: Any, messageDesc: Desc, message: MessageShape<Desc>): MessageShape<Desc> | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bufbuild/protobuf",
3
- "version": "2.0.0-alpha.3",
3
+ "version": "2.0.0-alpha.4",
4
4
  "license": "(Apache-2.0 AND BSD-3-Clause)",
5
5
  "description": "A complete implementation of Protocol Buffers in TypeScript, suitable for web browsers and Node.js.",
6
6
  "repository": {