@bufbuild/protobuf 2.11.0 → 2.12.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.
- package/README.md +3 -3
- package/dist/commonjs/codegenv1/boot.d.ts +1 -0
- package/dist/{cjs/codegenv1/types.js → commonjs/codegenv1/boot.js} +3 -7
- package/dist/{cjs → commonjs}/codegenv1/types.d.ts +9 -5
- package/dist/{cjs → commonjs}/codegenv2/types.d.ts +9 -5
- package/dist/{cjs → commonjs}/descriptors.d.ts +12 -5
- package/dist/{cjs → commonjs}/equals.d.ts +8 -3
- package/dist/{cjs → commonjs}/equals.js +8 -3
- package/dist/{cjs → commonjs}/extensions.d.ts +2 -1
- package/dist/{cjs → commonjs}/extensions.js +3 -4
- package/dist/{cjs → commonjs}/from-binary.d.ts +16 -2
- package/dist/{cjs → commonjs}/from-binary.js +37 -31
- package/dist/{cjs → commonjs}/from-json.d.ts +20 -3
- package/dist/{cjs → commonjs}/from-json.js +175 -55
- package/dist/commonjs/json-value.js +15 -0
- package/dist/commonjs/package.json +4 -0
- package/dist/{cjs → commonjs}/proto-int64.js +1 -0
- package/dist/{cjs → commonjs}/reflect/path.d.ts +1 -1
- package/dist/{cjs → commonjs}/reflect/reflect-check.js +3 -1
- package/dist/commonjs/reflect/scalar.d.ts +43 -0
- package/dist/{cjs → commonjs}/reflect/scalar.js +33 -6
- package/dist/{cjs → commonjs}/registry.js +24 -1
- package/dist/{cjs → commonjs}/to-json.d.ts +1 -1
- package/dist/{cjs → commonjs}/to-json.js +9 -10
- package/dist/{cjs → commonjs}/types.d.ts +1 -1
- package/dist/{cjs/codegenv2 → commonjs}/types.js +0 -7
- package/dist/{cjs → commonjs}/wire/binary-encoding.d.ts +13 -9
- package/dist/{cjs → commonjs}/wire/binary-encoding.js +26 -11
- package/dist/{cjs → commonjs}/wire/size-delimited.d.ts +1 -1
- package/dist/{cjs → commonjs}/wire/text-encoding.d.ts +4 -2
- package/dist/{cjs → commonjs}/wire/text-encoding.js +8 -1
- package/dist/{cjs → commonjs}/wkt/gen/google/protobuf/api_pb.d.ts +1 -1
- package/dist/{cjs → commonjs}/wkt/gen/google/protobuf/compiler/plugin_pb.d.ts +2 -2
- package/dist/{cjs → commonjs}/wkt/gen/google/protobuf/descriptor_pb.d.ts +37 -23
- package/dist/{cjs → commonjs}/wkt/gen/google/protobuf/descriptor_pb.js +1 -1
- package/dist/{cjs → commonjs}/wkt/gen/google/protobuf/field_mask_pb.d.ts +32 -36
- package/dist/{cjs → commonjs}/wkt/gen/google/protobuf/go_features_pb.d.ts +65 -0
- package/dist/{cjs → commonjs}/wkt/gen/google/protobuf/go_features_pb.js +38 -2
- package/dist/{cjs → commonjs}/wkt/gen/google/protobuf/timestamp_pb.d.ts +5 -5
- package/dist/{cjs → commonjs}/wkt/gen/google/protobuf/type_pb.d.ts +3 -3
- package/dist/{cjs → commonjs}/wkt/wrappers.d.ts +10 -0
- package/dist/{cjs → commonjs}/wkt/wrappers.js +24 -0
- package/dist/esm/codegenv1/boot.d.ts +1 -0
- package/dist/esm/codegenv1/boot.js +14 -0
- package/dist/esm/codegenv1/types.d.ts +9 -5
- package/dist/esm/codegenv1/types.js +0 -7
- package/dist/esm/codegenv2/types.d.ts +9 -5
- package/dist/esm/codegenv2/types.js +0 -7
- package/dist/esm/descriptors.d.ts +12 -5
- package/dist/esm/equals.d.ts +8 -3
- package/dist/esm/equals.js +8 -3
- package/dist/esm/extensions.d.ts +2 -1
- package/dist/esm/extensions.js +4 -5
- package/dist/esm/from-binary.d.ts +16 -2
- package/dist/esm/from-binary.js +36 -31
- package/dist/esm/from-json.d.ts +20 -3
- package/dist/esm/from-json.js +176 -56
- package/dist/esm/package.json +4 -0
- package/dist/esm/proto-int64.js +1 -0
- package/dist/esm/reflect/path.d.ts +1 -1
- package/dist/esm/reflect/reflect-check.js +3 -1
- package/dist/esm/reflect/scalar.d.ts +27 -5
- package/dist/esm/reflect/scalar.js +33 -6
- package/dist/esm/registry.js +24 -1
- package/dist/esm/to-json.d.ts +1 -1
- package/dist/esm/to-json.js +10 -11
- package/dist/esm/types.d.ts +1 -1
- package/dist/esm/wire/binary-encoding.d.ts +13 -9
- package/dist/esm/wire/binary-encoding.js +26 -11
- package/dist/esm/wire/size-delimited.d.ts +1 -1
- package/dist/esm/wire/text-encoding.d.ts +4 -2
- package/dist/esm/wire/text-encoding.js +8 -1
- package/dist/esm/wkt/gen/google/protobuf/api_pb.d.ts +1 -1
- package/dist/esm/wkt/gen/google/protobuf/compiler/plugin_pb.d.ts +2 -2
- package/dist/esm/wkt/gen/google/protobuf/descriptor_pb.d.ts +37 -23
- package/dist/esm/wkt/gen/google/protobuf/descriptor_pb.js +1 -1
- package/dist/esm/wkt/gen/google/protobuf/field_mask_pb.d.ts +32 -36
- package/dist/esm/wkt/gen/google/protobuf/go_features_pb.d.ts +65 -0
- package/dist/esm/wkt/gen/google/protobuf/go_features_pb.js +37 -1
- package/dist/esm/wkt/gen/google/protobuf/timestamp_pb.d.ts +5 -5
- package/dist/esm/wkt/gen/google/protobuf/type_pb.d.ts +3 -3
- package/dist/esm/wkt/wrappers.d.ts +10 -0
- package/dist/esm/wkt/wrappers.js +23 -0
- package/package.json +97 -31
- package/dist/cjs/package.json +0 -1
- package/dist/cjs/reflect/scalar.d.ts +0 -21
- /package/dist/{cjs → commonjs}/clone.d.ts +0 -0
- /package/dist/{cjs → commonjs}/clone.js +0 -0
- /package/dist/{cjs → commonjs}/codegenv1/enum.d.ts +0 -0
- /package/dist/{cjs → commonjs}/codegenv1/enum.js +0 -0
- /package/dist/{cjs → commonjs}/codegenv1/extension.d.ts +0 -0
- /package/dist/{cjs → commonjs}/codegenv1/extension.js +0 -0
- /package/dist/{cjs → commonjs}/codegenv1/file.d.ts +0 -0
- /package/dist/{cjs → commonjs}/codegenv1/file.js +0 -0
- /package/dist/{cjs → commonjs}/codegenv1/index.d.ts +0 -0
- /package/dist/{cjs → commonjs}/codegenv1/index.js +0 -0
- /package/dist/{cjs → commonjs}/codegenv1/message.d.ts +0 -0
- /package/dist/{cjs → commonjs}/codegenv1/message.js +0 -0
- /package/dist/{cjs → commonjs}/codegenv1/service.d.ts +0 -0
- /package/dist/{cjs → commonjs}/codegenv1/service.js +0 -0
- /package/dist/{cjs → commonjs}/codegenv1/symbols.d.ts +0 -0
- /package/dist/{cjs → commonjs}/codegenv1/symbols.js +0 -0
- /package/dist/{cjs → commonjs/codegenv1}/types.js +0 -0
- /package/dist/{cjs → commonjs}/codegenv2/boot.d.ts +0 -0
- /package/dist/{cjs → commonjs}/codegenv2/boot.js +0 -0
- /package/dist/{cjs → commonjs}/codegenv2/embed.d.ts +0 -0
- /package/dist/{cjs → commonjs}/codegenv2/embed.js +0 -0
- /package/dist/{cjs → commonjs}/codegenv2/enum.d.ts +0 -0
- /package/dist/{cjs → commonjs}/codegenv2/enum.js +0 -0
- /package/dist/{cjs → commonjs}/codegenv2/extension.d.ts +0 -0
- /package/dist/{cjs → commonjs}/codegenv2/extension.js +0 -0
- /package/dist/{cjs → commonjs}/codegenv2/file.d.ts +0 -0
- /package/dist/{cjs → commonjs}/codegenv2/file.js +0 -0
- /package/dist/{cjs → commonjs}/codegenv2/index.d.ts +0 -0
- /package/dist/{cjs → commonjs}/codegenv2/index.js +0 -0
- /package/dist/{cjs → commonjs}/codegenv2/message.d.ts +0 -0
- /package/dist/{cjs → commonjs}/codegenv2/message.js +0 -0
- /package/dist/{cjs → commonjs}/codegenv2/restore-json-names.d.ts +0 -0
- /package/dist/{cjs → commonjs}/codegenv2/restore-json-names.js +0 -0
- /package/dist/{cjs → commonjs}/codegenv2/scalar.d.ts +0 -0
- /package/dist/{cjs → commonjs}/codegenv2/scalar.js +0 -0
- /package/dist/{cjs → commonjs}/codegenv2/service.d.ts +0 -0
- /package/dist/{cjs → commonjs}/codegenv2/service.js +0 -0
- /package/dist/{cjs → commonjs}/codegenv2/symbols.d.ts +0 -0
- /package/dist/{cjs → commonjs}/codegenv2/symbols.js +0 -0
- /package/dist/{cjs/json-value.js → commonjs/codegenv2/types.js} +0 -0
- /package/dist/{cjs → commonjs}/create.d.ts +0 -0
- /package/dist/{cjs → commonjs}/create.js +0 -0
- /package/dist/{cjs → commonjs}/descriptors.js +0 -0
- /package/dist/{cjs → commonjs}/fields.d.ts +0 -0
- /package/dist/{cjs → commonjs}/fields.js +0 -0
- /package/dist/{cjs → commonjs}/index.d.ts +0 -0
- /package/dist/{cjs → commonjs}/index.js +0 -0
- /package/dist/{cjs → commonjs}/is-message.d.ts +0 -0
- /package/dist/{cjs → commonjs}/is-message.js +0 -0
- /package/dist/{cjs → commonjs}/json-value.d.ts +0 -0
- /package/dist/{cjs → commonjs}/merge.d.ts +0 -0
- /package/dist/{cjs → commonjs}/merge.js +0 -0
- /package/dist/{cjs → commonjs}/proto-int64.d.ts +0 -0
- /package/dist/{cjs → commonjs}/reflect/error.d.ts +0 -0
- /package/dist/{cjs → commonjs}/reflect/error.js +0 -0
- /package/dist/{cjs → commonjs}/reflect/guard.d.ts +0 -0
- /package/dist/{cjs → commonjs}/reflect/guard.js +0 -0
- /package/dist/{cjs → commonjs}/reflect/index.d.ts +0 -0
- /package/dist/{cjs → commonjs}/reflect/index.js +0 -0
- /package/dist/{cjs → commonjs}/reflect/names.d.ts +0 -0
- /package/dist/{cjs → commonjs}/reflect/names.js +0 -0
- /package/dist/{cjs → commonjs}/reflect/nested-types.d.ts +0 -0
- /package/dist/{cjs → commonjs}/reflect/nested-types.js +0 -0
- /package/dist/{cjs → commonjs}/reflect/path.js +0 -0
- /package/dist/{cjs → commonjs}/reflect/reflect-check.d.ts +0 -0
- /package/dist/{cjs → commonjs}/reflect/reflect-types.d.ts +0 -0
- /package/dist/{cjs → commonjs}/reflect/reflect-types.js +0 -0
- /package/dist/{cjs → commonjs}/reflect/reflect.d.ts +0 -0
- /package/dist/{cjs → commonjs}/reflect/reflect.js +0 -0
- /package/dist/{cjs → commonjs}/reflect/unsafe.d.ts +0 -0
- /package/dist/{cjs → commonjs}/reflect/unsafe.js +0 -0
- /package/dist/{cjs → commonjs}/registry.d.ts +0 -0
- /package/dist/{cjs → commonjs}/to-binary.d.ts +0 -0
- /package/dist/{cjs → commonjs}/to-binary.js +0 -0
- /package/dist/{cjs → commonjs}/wire/base64-encoding.d.ts +0 -0
- /package/dist/{cjs → commonjs}/wire/base64-encoding.js +0 -0
- /package/dist/{cjs → commonjs}/wire/index.d.ts +0 -0
- /package/dist/{cjs → commonjs}/wire/index.js +0 -0
- /package/dist/{cjs → commonjs}/wire/size-delimited.js +0 -0
- /package/dist/{cjs → commonjs}/wire/text-format.d.ts +0 -0
- /package/dist/{cjs → commonjs}/wire/text-format.js +0 -0
- /package/dist/{cjs → commonjs}/wire/varint.d.ts +0 -0
- /package/dist/{cjs → commonjs}/wire/varint.js +0 -0
- /package/dist/{cjs → commonjs}/wkt/any.d.ts +0 -0
- /package/dist/{cjs → commonjs}/wkt/any.js +0 -0
- /package/dist/{cjs → commonjs}/wkt/duration.d.ts +0 -0
- /package/dist/{cjs → commonjs}/wkt/duration.js +0 -0
- /package/dist/{cjs → commonjs}/wkt/gen/google/protobuf/any_pb.d.ts +0 -0
- /package/dist/{cjs → commonjs}/wkt/gen/google/protobuf/any_pb.js +0 -0
- /package/dist/{cjs → commonjs}/wkt/gen/google/protobuf/api_pb.js +0 -0
- /package/dist/{cjs → commonjs}/wkt/gen/google/protobuf/compiler/plugin_pb.js +0 -0
- /package/dist/{cjs → commonjs}/wkt/gen/google/protobuf/cpp_features_pb.d.ts +0 -0
- /package/dist/{cjs → commonjs}/wkt/gen/google/protobuf/cpp_features_pb.js +0 -0
- /package/dist/{cjs → commonjs}/wkt/gen/google/protobuf/duration_pb.d.ts +0 -0
- /package/dist/{cjs → commonjs}/wkt/gen/google/protobuf/duration_pb.js +0 -0
- /package/dist/{cjs → commonjs}/wkt/gen/google/protobuf/empty_pb.d.ts +0 -0
- /package/dist/{cjs → commonjs}/wkt/gen/google/protobuf/empty_pb.js +0 -0
- /package/dist/{cjs → commonjs}/wkt/gen/google/protobuf/field_mask_pb.js +0 -0
- /package/dist/{cjs → commonjs}/wkt/gen/google/protobuf/java_features_pb.d.ts +0 -0
- /package/dist/{cjs → commonjs}/wkt/gen/google/protobuf/java_features_pb.js +0 -0
- /package/dist/{cjs → commonjs}/wkt/gen/google/protobuf/source_context_pb.d.ts +0 -0
- /package/dist/{cjs → commonjs}/wkt/gen/google/protobuf/source_context_pb.js +0 -0
- /package/dist/{cjs → commonjs}/wkt/gen/google/protobuf/struct_pb.d.ts +0 -0
- /package/dist/{cjs → commonjs}/wkt/gen/google/protobuf/struct_pb.js +0 -0
- /package/dist/{cjs → commonjs}/wkt/gen/google/protobuf/timestamp_pb.js +0 -0
- /package/dist/{cjs → commonjs}/wkt/gen/google/protobuf/type_pb.js +0 -0
- /package/dist/{cjs → commonjs}/wkt/gen/google/protobuf/wrappers_pb.d.ts +0 -0
- /package/dist/{cjs → commonjs}/wkt/gen/google/protobuf/wrappers_pb.js +0 -0
- /package/dist/{cjs → commonjs}/wkt/index.d.ts +0 -0
- /package/dist/{cjs → commonjs}/wkt/index.js +0 -0
- /package/dist/{cjs → commonjs}/wkt/timestamp.d.ts +0 -0
- /package/dist/{cjs → commonjs}/wkt/timestamp.js +0 -0
package/dist/esm/from-json.js
CHANGED
|
@@ -19,40 +19,44 @@ import { FieldError, isFieldError } from "./reflect/error.js";
|
|
|
19
19
|
import { formatVal } from "./reflect/reflect-check.js";
|
|
20
20
|
import { protoSnakeCase } from "./reflect/names.js";
|
|
21
21
|
import { base64Decode } from "./wire/base64-encoding.js";
|
|
22
|
-
import { isWrapperDesc, anyPack, ListValueSchema, NullValue, StructSchema, ValueSchema, } from "./wkt/index.js";
|
|
22
|
+
import { hasCustomJsonRepresentation, isWrapperDesc, anyPack, ListValueSchema, NullValue, StructSchema, ValueSchema, } from "./wkt/index.js";
|
|
23
23
|
import { createExtensionContainer, setExtension } from "./extensions.js";
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
ignoreUnknownFields: false,
|
|
27
|
-
};
|
|
28
|
-
function makeReadOptions(options) {
|
|
29
|
-
return options ? Object.assign(Object.assign({}, jsonReadDefaults), options) : jsonReadDefaults;
|
|
24
|
+
function makeReadContext(options) {
|
|
25
|
+
return Object.assign(Object.assign({ ignoreUnknownFields: false, recursionLimit: 100 }, options), { depth: 0 });
|
|
30
26
|
}
|
|
31
27
|
/**
|
|
32
28
|
* Parse a message from a JSON string.
|
|
29
|
+
*
|
|
30
|
+
* Duplicate keys are rejected.
|
|
33
31
|
*/
|
|
34
32
|
export function fromJsonString(schema, json, options) {
|
|
35
33
|
return fromJson(schema, parseJsonString(json, schema.typeName), options);
|
|
36
34
|
}
|
|
37
35
|
/**
|
|
38
|
-
* Parse a message from a JSON string, merging fields.
|
|
36
|
+
* Parse a message from a JSON string, merging fields into the target.
|
|
39
37
|
*
|
|
40
38
|
* Repeated fields are appended. Map entries are added, overwriting
|
|
41
39
|
* existing keys.
|
|
42
40
|
*
|
|
43
41
|
* If a message field is already present, it will be merged with the
|
|
44
42
|
* new data.
|
|
43
|
+
*
|
|
44
|
+
* Duplicate keys in the JSON are rejected, as in `fromJsonString`.
|
|
45
45
|
*/
|
|
46
46
|
export function mergeFromJsonString(schema, target, json, options) {
|
|
47
47
|
return mergeFromJson(schema, target, parseJsonString(json, schema.typeName), options);
|
|
48
48
|
}
|
|
49
49
|
/**
|
|
50
50
|
* Parse a message from a JSON value.
|
|
51
|
+
*
|
|
52
|
+
* Duplicate keys are rejected, but a value parsed by JSON.parse has already
|
|
53
|
+
* dropped duplicates (the last one wins). Use `fromJsonString` for strict
|
|
54
|
+
* duplicate-key checking.
|
|
51
55
|
*/
|
|
52
56
|
export function fromJson(schema, json, options) {
|
|
53
57
|
const msg = reflect(schema);
|
|
54
58
|
try {
|
|
55
|
-
readMessage(msg, json,
|
|
59
|
+
readMessage(msg, json, makeReadContext(options));
|
|
56
60
|
}
|
|
57
61
|
catch (e) {
|
|
58
62
|
if (isFieldError(e)) {
|
|
@@ -66,17 +70,20 @@ export function fromJson(schema, json, options) {
|
|
|
66
70
|
return msg.message;
|
|
67
71
|
}
|
|
68
72
|
/**
|
|
69
|
-
* Parse a message from a JSON value, merging fields.
|
|
73
|
+
* Parse a message from a JSON value, merging fields into the target.
|
|
70
74
|
*
|
|
71
75
|
* Repeated fields are appended. Map entries are added, overwriting
|
|
72
76
|
* existing keys.
|
|
73
77
|
*
|
|
74
78
|
* If a message field is already present, it will be merged with the
|
|
75
79
|
* new data.
|
|
80
|
+
*
|
|
81
|
+
* Duplicate keys are rejected as in `fromJson`; use `mergeFromJsonString`
|
|
82
|
+
* for strict checking.
|
|
76
83
|
*/
|
|
77
84
|
export function mergeFromJson(schema, target, json, options) {
|
|
78
85
|
try {
|
|
79
|
-
readMessage(reflect(schema, target), json,
|
|
86
|
+
readMessage(reflect(schema, target), json, makeReadContext(options));
|
|
80
87
|
}
|
|
81
88
|
catch (e) {
|
|
82
89
|
if (isFieldError(e)) {
|
|
@@ -113,82 +120,95 @@ function getJsonField(desc, jsonKey) {
|
|
|
113
120
|
}
|
|
114
121
|
return (_a = messageJsonFields.get(desc)) === null || _a === void 0 ? void 0 : _a.get(jsonKey);
|
|
115
122
|
}
|
|
116
|
-
function readMessage(msg, json,
|
|
123
|
+
function readMessage(msg, json, ctx) {
|
|
117
124
|
var _a;
|
|
118
|
-
if (
|
|
125
|
+
if (++ctx.depth > ctx.recursionLimit) {
|
|
126
|
+
throw new Error(`cannot decode ${msg.desc} from JSON: maximum recursion depth of ${ctx.recursionLimit} reached`);
|
|
127
|
+
}
|
|
128
|
+
if (tryWktFromJson(msg, json, ctx)) {
|
|
129
|
+
ctx.depth--;
|
|
119
130
|
return;
|
|
120
131
|
}
|
|
121
132
|
if (json == null || Array.isArray(json) || typeof json != "object") {
|
|
122
133
|
throw new Error(`cannot decode ${msg.desc} from JSON: ${formatVal(json)}`);
|
|
123
134
|
}
|
|
124
135
|
const oneofSeen = new Map();
|
|
136
|
+
const fieldSeen = new Set();
|
|
125
137
|
for (const [jsonKey, jsonValue] of Object.entries(json)) {
|
|
126
138
|
const field = getJsonField(msg.desc, jsonKey);
|
|
127
139
|
if (field) {
|
|
140
|
+
if (fieldSeen.has(field)) {
|
|
141
|
+
// The same field may be set by its proto name and its JSON name, or by
|
|
142
|
+
// a duplicate or unicode-escaped key that JSON.parse already collapsed.
|
|
143
|
+
// Checked before the null-skip below so that a null entry still counts.
|
|
144
|
+
throw new FieldError(field, "set multiple times");
|
|
145
|
+
}
|
|
146
|
+
fieldSeen.add(field);
|
|
147
|
+
if (field.oneof && jsonValue === null && field.fieldKind == "scalar") {
|
|
148
|
+
// see conformance test Required.Proto3.JsonInput.OneofFieldNull{First,Second}
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
128
151
|
if (field.oneof) {
|
|
129
|
-
if (jsonValue === null && field.fieldKind == "scalar") {
|
|
130
|
-
// see conformance test Required.Proto3.JsonInput.OneofFieldNull{First,Second}
|
|
131
|
-
continue;
|
|
132
|
-
}
|
|
133
152
|
const seen = oneofSeen.get(field.oneof);
|
|
134
153
|
if (seen !== undefined) {
|
|
135
154
|
throw new FieldError(field.oneof, `oneof set multiple times by ${seen.name} and ${field.name}`);
|
|
136
155
|
}
|
|
137
156
|
oneofSeen.set(field.oneof, field);
|
|
138
157
|
}
|
|
139
|
-
readField(msg, field, jsonValue,
|
|
158
|
+
readField(msg, field, jsonValue, ctx);
|
|
140
159
|
}
|
|
141
160
|
else {
|
|
142
161
|
let extension = undefined;
|
|
143
162
|
if (jsonKey.startsWith("[") &&
|
|
144
163
|
jsonKey.endsWith("]") &&
|
|
145
164
|
// biome-ignore lint/suspicious/noAssignInExpressions: no
|
|
146
|
-
(extension = (_a =
|
|
165
|
+
(extension = (_a = ctx.registry) === null || _a === void 0 ? void 0 : _a.getExtension(jsonKey.substring(1, jsonKey.length - 1))) &&
|
|
147
166
|
extension.extendee.typeName === msg.desc.typeName) {
|
|
148
167
|
const [container, field, get] = createExtensionContainer(extension);
|
|
149
|
-
readField(container, field, jsonValue,
|
|
168
|
+
readField(container, field, jsonValue, ctx);
|
|
150
169
|
setExtension(msg.message, extension, get());
|
|
151
170
|
}
|
|
152
|
-
if (!extension && !
|
|
171
|
+
if (!extension && !ctx.ignoreUnknownFields) {
|
|
153
172
|
throw new Error(`cannot decode ${msg.desc} from JSON: key "${jsonKey}" is unknown`);
|
|
154
173
|
}
|
|
155
174
|
}
|
|
156
175
|
}
|
|
176
|
+
ctx.depth--;
|
|
157
177
|
}
|
|
158
|
-
function readField(msg, field, json,
|
|
178
|
+
function readField(msg, field, json, ctx) {
|
|
159
179
|
switch (field.fieldKind) {
|
|
160
180
|
case "scalar":
|
|
161
181
|
readScalarField(msg, field, json);
|
|
162
182
|
break;
|
|
163
183
|
case "enum":
|
|
164
|
-
readEnumField(msg, field, json,
|
|
184
|
+
readEnumField(msg, field, json, ctx);
|
|
165
185
|
break;
|
|
166
186
|
case "message":
|
|
167
|
-
readMessageField(msg, field, json,
|
|
187
|
+
readMessageField(msg, field, json, ctx);
|
|
168
188
|
break;
|
|
169
189
|
case "list":
|
|
170
|
-
readListField(msg.get(field), json,
|
|
190
|
+
readListField(msg.get(field), json, ctx);
|
|
171
191
|
break;
|
|
172
192
|
case "map":
|
|
173
|
-
readMapField(msg.get(field), json,
|
|
193
|
+
readMapField(msg.get(field), json, ctx);
|
|
174
194
|
break;
|
|
175
195
|
}
|
|
176
196
|
}
|
|
177
|
-
function readListOrMapItem(field, json,
|
|
197
|
+
function readListOrMapItem(field, json, ctx) {
|
|
178
198
|
if (field.scalar && json !== null) {
|
|
179
199
|
return scalarFromJson(field, json);
|
|
180
200
|
}
|
|
181
201
|
if (field.message && !isResetSentinelNullValue(field, json)) {
|
|
182
202
|
const msgValue = reflect(field.message);
|
|
183
|
-
readMessage(msgValue, json,
|
|
203
|
+
readMessage(msgValue, json, ctx);
|
|
184
204
|
return msgValue;
|
|
185
205
|
}
|
|
186
206
|
if (field.enum && !isResetSentinelNullValue(field, json)) {
|
|
187
|
-
return readEnum(field.enum, json,
|
|
207
|
+
return readEnum(field.enum, json, ctx.ignoreUnknownFields);
|
|
188
208
|
}
|
|
189
209
|
throw new FieldError(field, `${field.fieldKind === "list" ? "list item" : "map value"} must not be null`);
|
|
190
210
|
}
|
|
191
|
-
function readMapField(map, json,
|
|
211
|
+
function readMapField(map, json, ctx) {
|
|
192
212
|
if (json === null) {
|
|
193
213
|
return;
|
|
194
214
|
}
|
|
@@ -196,15 +216,20 @@ function readMapField(map, json, opts) {
|
|
|
196
216
|
if (typeof json != "object" || Array.isArray(json)) {
|
|
197
217
|
throw new FieldError(field, "expected object, got " + formatVal(json));
|
|
198
218
|
}
|
|
219
|
+
const seen = new Set();
|
|
199
220
|
for (const [jsonMapKey, jsonMapValue] of Object.entries(json)) {
|
|
200
221
|
const key = mapKeyFromJson(field.mapKey, jsonMapKey);
|
|
201
|
-
|
|
222
|
+
if (seen.has(key)) {
|
|
223
|
+
throw new FieldError(field, `duplicate map key "${jsonMapKey}"`);
|
|
224
|
+
}
|
|
225
|
+
seen.add(key);
|
|
226
|
+
const value = readListOrMapItem(field, jsonMapValue, ctx);
|
|
202
227
|
if (value !== tokenIgnoredUnknownEnum) {
|
|
203
228
|
map.set(key, value);
|
|
204
229
|
}
|
|
205
230
|
}
|
|
206
231
|
}
|
|
207
|
-
function readListField(list, json,
|
|
232
|
+
function readListField(list, json, ctx) {
|
|
208
233
|
if (json === null) {
|
|
209
234
|
return;
|
|
210
235
|
}
|
|
@@ -213,27 +238,27 @@ function readListField(list, json, opts) {
|
|
|
213
238
|
throw new FieldError(field, "expected Array, got " + formatVal(json));
|
|
214
239
|
}
|
|
215
240
|
for (const jsonItem of json) {
|
|
216
|
-
const value = readListOrMapItem(field, jsonItem,
|
|
241
|
+
const value = readListOrMapItem(field, jsonItem, ctx);
|
|
217
242
|
if (value !== tokenIgnoredUnknownEnum) {
|
|
218
243
|
list.add(value);
|
|
219
244
|
}
|
|
220
245
|
}
|
|
221
246
|
}
|
|
222
|
-
function readMessageField(msg, field, json,
|
|
247
|
+
function readMessageField(msg, field, json, ctx) {
|
|
223
248
|
if (isResetSentinelNullValue(field, json)) {
|
|
224
249
|
msg.clear(field);
|
|
225
250
|
return;
|
|
226
251
|
}
|
|
227
252
|
const msgValue = msg.isSet(field) ? msg.get(field) : reflect(field.message);
|
|
228
|
-
readMessage(msgValue, json,
|
|
253
|
+
readMessage(msgValue, json, ctx);
|
|
229
254
|
msg.set(field, msgValue);
|
|
230
255
|
}
|
|
231
|
-
function readEnumField(msg, field, json,
|
|
256
|
+
function readEnumField(msg, field, json, ctx) {
|
|
232
257
|
if (isResetSentinelNullValue(field, json)) {
|
|
233
258
|
msg.clear(field);
|
|
234
259
|
return;
|
|
235
260
|
}
|
|
236
|
-
const enumValue = readEnum(field.enum, json,
|
|
261
|
+
const enumValue = readEnum(field.enum, json, ctx.ignoreUnknownFields);
|
|
237
262
|
if (enumValue !== tokenIgnoredUnknownEnum) {
|
|
238
263
|
msg.set(field, enumValue);
|
|
239
264
|
}
|
|
@@ -362,7 +387,8 @@ function scalarFromJson(field, json) {
|
|
|
362
387
|
}
|
|
363
388
|
/**
|
|
364
389
|
* Try to parse a JSON value to a map key for the reflect API.
|
|
365
|
-
*
|
|
390
|
+
* Canonicalizes 64-bit integers given as string, so that "01 and "1" are one
|
|
391
|
+
* key, and duplicates can raise an error.
|
|
366
392
|
* Returns the input if the JSON value cannot be converted.
|
|
367
393
|
*/
|
|
368
394
|
function mapKeyFromJson(type, jsonString) {
|
|
@@ -381,6 +407,14 @@ function mapKeyFromJson(type, jsonString) {
|
|
|
381
407
|
case ScalarType.SFIXED32:
|
|
382
408
|
case ScalarType.SINT32:
|
|
383
409
|
return int32FromJson(jsonString);
|
|
410
|
+
case ScalarType.INT64:
|
|
411
|
+
case ScalarType.SINT64:
|
|
412
|
+
case ScalarType.SFIXED64:
|
|
413
|
+
case ScalarType.UINT64:
|
|
414
|
+
case ScalarType.FIXED64:
|
|
415
|
+
return /^-?0+$/.test(jsonString)
|
|
416
|
+
? "0"
|
|
417
|
+
: jsonString.replace(/^(-?)0+(?=\d)/, "$1");
|
|
384
418
|
default:
|
|
385
419
|
return jsonString;
|
|
386
420
|
}
|
|
@@ -409,9 +443,14 @@ function int32FromJson(json) {
|
|
|
409
443
|
}
|
|
410
444
|
return json;
|
|
411
445
|
}
|
|
446
|
+
/**
|
|
447
|
+
* Parse a JSON string, rejecting duplicate object keys (which JSON.parse would
|
|
448
|
+
* otherwise silently merge).
|
|
449
|
+
*/
|
|
412
450
|
function parseJsonString(jsonString, typeName) {
|
|
451
|
+
let json;
|
|
413
452
|
try {
|
|
414
|
-
|
|
453
|
+
json = JSON.parse(jsonString);
|
|
415
454
|
}
|
|
416
455
|
catch (e) {
|
|
417
456
|
const message = e instanceof Error ? e.message : String(e);
|
|
@@ -419,14 +458,91 @@ function parseJsonString(jsonString, typeName) {
|
|
|
419
458
|
// @ts-expect-error we use the ES2022 error CTOR option "cause" for better stack traces
|
|
420
459
|
{ cause: e });
|
|
421
460
|
}
|
|
461
|
+
checkDuplicateKeys(jsonString, typeName);
|
|
462
|
+
return json;
|
|
422
463
|
}
|
|
423
|
-
|
|
464
|
+
/**
|
|
465
|
+
* Scan a JSON string for duplicate object member names at any depth, throwing
|
|
466
|
+
* if any are found. JSON.parse() silently keeps the last of duplicate keys, so
|
|
467
|
+
* this raw-string scan is the only way to reject them. It must only be called
|
|
468
|
+
* with a string that JSON.parse() has already accepted, so it can assume the
|
|
469
|
+
* input is well-formed.
|
|
470
|
+
*/
|
|
471
|
+
function checkDuplicateKeys(jsonString, typeName) {
|
|
472
|
+
// One Set of seen member names for each open object; arrays push null.
|
|
473
|
+
const stack = [];
|
|
474
|
+
// Whether the next string token is an object member name.
|
|
475
|
+
let expectKey = false;
|
|
476
|
+
let i = 0;
|
|
477
|
+
while (i < jsonString.length) {
|
|
478
|
+
switch (jsonString[i]) {
|
|
479
|
+
case "{":
|
|
480
|
+
stack.push(new Set());
|
|
481
|
+
expectKey = true;
|
|
482
|
+
i++;
|
|
483
|
+
break;
|
|
484
|
+
case "[":
|
|
485
|
+
stack.push(null);
|
|
486
|
+
expectKey = false;
|
|
487
|
+
i++;
|
|
488
|
+
break;
|
|
489
|
+
case "}":
|
|
490
|
+
case "]":
|
|
491
|
+
stack.pop();
|
|
492
|
+
expectKey = false;
|
|
493
|
+
i++;
|
|
494
|
+
break;
|
|
495
|
+
case ",":
|
|
496
|
+
expectKey = stack[stack.length - 1] != null;
|
|
497
|
+
i++;
|
|
498
|
+
break;
|
|
499
|
+
case ":":
|
|
500
|
+
expectKey = false;
|
|
501
|
+
i++;
|
|
502
|
+
break;
|
|
503
|
+
case '"': {
|
|
504
|
+
const open = i++;
|
|
505
|
+
let escaped = false;
|
|
506
|
+
while (i < jsonString.length) {
|
|
507
|
+
if (jsonString[i] == "\\") {
|
|
508
|
+
escaped = true;
|
|
509
|
+
i += 2; // skip the backslash and the character it escapes
|
|
510
|
+
continue;
|
|
511
|
+
}
|
|
512
|
+
if (jsonString[i] == '"') {
|
|
513
|
+
break;
|
|
514
|
+
}
|
|
515
|
+
i++;
|
|
516
|
+
}
|
|
517
|
+
const close = i++;
|
|
518
|
+
const seen = stack[stack.length - 1];
|
|
519
|
+
if (expectKey && seen) {
|
|
520
|
+
// Decode escapes (rare) so that, for example, a key written with a
|
|
521
|
+
// unicode escape collides with the same key written literally.
|
|
522
|
+
const name = escaped
|
|
523
|
+
? JSON.parse(jsonString.substring(open, close + 1))
|
|
524
|
+
: jsonString.substring(open + 1, close);
|
|
525
|
+
if (seen.has(name)) {
|
|
526
|
+
throw new Error(`cannot decode message ${typeName} from JSON: duplicate object key "${name}"`);
|
|
527
|
+
}
|
|
528
|
+
seen.add(name);
|
|
529
|
+
}
|
|
530
|
+
expectKey = false;
|
|
531
|
+
break;
|
|
532
|
+
}
|
|
533
|
+
default:
|
|
534
|
+
i++;
|
|
535
|
+
break;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
function tryWktFromJson(msg, jsonValue, ctx) {
|
|
424
540
|
if (!msg.desc.typeName.startsWith("google.protobuf.")) {
|
|
425
541
|
return false;
|
|
426
542
|
}
|
|
427
543
|
switch (msg.desc.typeName) {
|
|
428
544
|
case "google.protobuf.Any":
|
|
429
|
-
anyFromJson(msg.message, jsonValue,
|
|
545
|
+
anyFromJson(msg.message, jsonValue, ctx);
|
|
430
546
|
return true;
|
|
431
547
|
case "google.protobuf.Timestamp":
|
|
432
548
|
timestampFromJson(msg.message, jsonValue);
|
|
@@ -438,13 +554,13 @@ function tryWktFromJson(msg, jsonValue, opts) {
|
|
|
438
554
|
fieldMaskFromJson(msg.message, jsonValue);
|
|
439
555
|
return true;
|
|
440
556
|
case "google.protobuf.Struct":
|
|
441
|
-
structFromJson(msg.message, jsonValue);
|
|
557
|
+
structFromJson(msg.message, jsonValue, ctx);
|
|
442
558
|
return true;
|
|
443
559
|
case "google.protobuf.Value":
|
|
444
|
-
valueFromJson(msg.message, jsonValue);
|
|
560
|
+
valueFromJson(msg.message, jsonValue, ctx);
|
|
445
561
|
return true;
|
|
446
562
|
case "google.protobuf.ListValue":
|
|
447
|
-
listValueFromJson(msg.message, jsonValue);
|
|
563
|
+
listValueFromJson(msg.message, jsonValue, ctx);
|
|
448
564
|
return true;
|
|
449
565
|
default:
|
|
450
566
|
if (isWrapperDesc(msg.desc)) {
|
|
@@ -460,7 +576,7 @@ function tryWktFromJson(msg, jsonValue, opts) {
|
|
|
460
576
|
return false;
|
|
461
577
|
}
|
|
462
578
|
}
|
|
463
|
-
function anyFromJson(any, json,
|
|
579
|
+
function anyFromJson(any, json, ctx) {
|
|
464
580
|
var _a;
|
|
465
581
|
if (json === null || Array.isArray(json) || typeof json != "object") {
|
|
466
582
|
throw new Error(`cannot decode message ${any.$typeName} from JSON: expected object but got ${formatVal(json)}`);
|
|
@@ -478,21 +594,21 @@ function anyFromJson(any, json, opts) {
|
|
|
478
594
|
if (!typeName.length) {
|
|
479
595
|
throw new Error(`cannot decode message ${any.$typeName} from JSON: "@type" is invalid`);
|
|
480
596
|
}
|
|
481
|
-
const desc = (_a =
|
|
597
|
+
const desc = (_a = ctx.registry) === null || _a === void 0 ? void 0 : _a.getMessage(typeName);
|
|
482
598
|
if (!desc) {
|
|
483
599
|
throw new Error(`cannot decode message ${any.$typeName} from JSON: ${typeUrl} is not in the type registry`);
|
|
484
600
|
}
|
|
485
601
|
const msg = reflect(desc);
|
|
486
|
-
if (
|
|
602
|
+
if (hasCustomJsonRepresentation(desc) &&
|
|
487
603
|
Object.prototype.hasOwnProperty.call(json, "value")) {
|
|
488
604
|
const value = json.value;
|
|
489
|
-
readMessage(msg, value,
|
|
605
|
+
readMessage(msg, value, ctx);
|
|
490
606
|
}
|
|
491
607
|
else {
|
|
492
608
|
const copy = Object.assign({}, json);
|
|
493
609
|
// biome-ignore lint/performance/noDelete: <explanation>
|
|
494
610
|
delete copy["@type"];
|
|
495
|
-
readMessage(msg, copy,
|
|
611
|
+
readMessage(msg, copy, ctx);
|
|
496
612
|
}
|
|
497
613
|
anyPack(msg.desc, msg.message, any);
|
|
498
614
|
}
|
|
@@ -558,17 +674,20 @@ function fieldMaskFromJson(fieldMask, json) {
|
|
|
558
674
|
return protoSnakeCase(path);
|
|
559
675
|
});
|
|
560
676
|
}
|
|
561
|
-
function structFromJson(struct, json) {
|
|
677
|
+
function structFromJson(struct, json, ctx) {
|
|
562
678
|
if (typeof json != "object" || json == null || Array.isArray(json)) {
|
|
563
679
|
throw new Error(`cannot decode message ${struct.$typeName} from JSON ${formatVal(json)}`);
|
|
564
680
|
}
|
|
565
681
|
for (const [k, v] of Object.entries(json)) {
|
|
566
682
|
const parsedV = create(ValueSchema);
|
|
567
|
-
valueFromJson(parsedV, v);
|
|
683
|
+
valueFromJson(parsedV, v, ctx);
|
|
568
684
|
struct.fields[k] = parsedV;
|
|
569
685
|
}
|
|
570
686
|
}
|
|
571
|
-
function valueFromJson(value, json) {
|
|
687
|
+
function valueFromJson(value, json, ctx) {
|
|
688
|
+
if (++ctx.depth > ctx.recursionLimit) {
|
|
689
|
+
throw new Error(`cannot decode ${value.$typeName} from JSON: maximum recursion depth of ${ctx.recursionLimit} reached`);
|
|
690
|
+
}
|
|
572
691
|
switch (typeof json) {
|
|
573
692
|
case "number":
|
|
574
693
|
value.kind = { case: "numberValue", value: json };
|
|
@@ -585,27 +704,28 @@ function valueFromJson(value, json) {
|
|
|
585
704
|
}
|
|
586
705
|
else if (Array.isArray(json)) {
|
|
587
706
|
const listValue = create(ListValueSchema);
|
|
588
|
-
listValueFromJson(listValue, json);
|
|
707
|
+
listValueFromJson(listValue, json, ctx);
|
|
589
708
|
value.kind = { case: "listValue", value: listValue };
|
|
590
709
|
}
|
|
591
710
|
else {
|
|
592
711
|
const struct = create(StructSchema);
|
|
593
|
-
structFromJson(struct, json);
|
|
712
|
+
structFromJson(struct, json, ctx);
|
|
594
713
|
value.kind = { case: "structValue", value: struct };
|
|
595
714
|
}
|
|
596
715
|
break;
|
|
597
716
|
default:
|
|
598
717
|
throw new Error(`cannot decode message ${value.$typeName} from JSON ${formatVal(json)}`);
|
|
599
718
|
}
|
|
719
|
+
ctx.depth--;
|
|
600
720
|
return value;
|
|
601
721
|
}
|
|
602
|
-
function listValueFromJson(listValue, json) {
|
|
722
|
+
function listValueFromJson(listValue, json, ctx) {
|
|
603
723
|
if (!Array.isArray(json)) {
|
|
604
724
|
throw new Error(`cannot decode message ${listValue.$typeName} from JSON ${formatVal(json)}`);
|
|
605
725
|
}
|
|
606
726
|
for (const e of json) {
|
|
607
727
|
const value = create(ValueSchema);
|
|
608
|
-
valueFromJson(value, e);
|
|
728
|
+
valueFromJson(value, e, ctx);
|
|
609
729
|
listValue.values.push(value);
|
|
610
730
|
}
|
|
611
731
|
}
|
package/dist/esm/proto-int64.js
CHANGED
|
@@ -25,6 +25,7 @@ function makeInt64Support() {
|
|
|
25
25
|
typeof dv.setBigInt64 === "function" &&
|
|
26
26
|
typeof dv.setBigUint64 === "function" &&
|
|
27
27
|
(!!globalThis.Deno ||
|
|
28
|
+
!!globalThis.Bun ||
|
|
28
29
|
typeof process != "object" ||
|
|
29
30
|
typeof process.env != "object" ||
|
|
30
31
|
process.env.BUF_BIGINT_DISABLE !== "1");
|
|
@@ -89,7 +89,7 @@ export declare function buildPath(schema: DescMessage): PathBuilder;
|
|
|
89
89
|
* paths that refer to an extension.
|
|
90
90
|
*/
|
|
91
91
|
export declare function parsePath(schema: DescMessage, path: string, options?: {
|
|
92
|
-
registry?: Registry;
|
|
92
|
+
registry?: Registry | undefined;
|
|
93
93
|
}): Path;
|
|
94
94
|
/**
|
|
95
95
|
* Stringify a path.
|
|
@@ -74,7 +74,9 @@ function checkSingular(field, value) {
|
|
|
74
74
|
}
|
|
75
75
|
if (field.enum !== undefined) {
|
|
76
76
|
if (field.enum.open) {
|
|
77
|
-
|
|
77
|
+
// Open enums accept unrecognized values, but enum values are always
|
|
78
|
+
// int32 (see https://protobuf.dev/programming-guides/proto3/#enum).
|
|
79
|
+
return checkScalarValue(value, ScalarType.INT32);
|
|
78
80
|
}
|
|
79
81
|
return field.enum.values.some((v) => v.number === value);
|
|
80
82
|
}
|
|
@@ -5,17 +5,39 @@ import { ScalarType } from "../descriptors.js";
|
|
|
5
5
|
export type ScalarValue<T = ScalarType, LongAsString extends boolean = false> = T extends ScalarType.STRING ? string : T extends ScalarType.INT32 ? number : T extends ScalarType.UINT32 ? number : T extends ScalarType.SINT32 ? number : T extends ScalarType.FIXED32 ? number : T extends ScalarType.SFIXED32 ? number : T extends ScalarType.FLOAT ? number : T extends ScalarType.DOUBLE ? number : T extends ScalarType.INT64 ? LongAsString extends true ? string : bigint : T extends ScalarType.SINT64 ? LongAsString extends true ? string : bigint : T extends ScalarType.SFIXED64 ? LongAsString extends true ? string : bigint : T extends ScalarType.UINT64 ? LongAsString extends true ? string : bigint : T extends ScalarType.FIXED64 ? LongAsString extends true ? string : bigint : T extends ScalarType.BOOL ? boolean : T extends ScalarType.BYTES ? Uint8Array : never;
|
|
6
6
|
/**
|
|
7
7
|
* Returns true if both scalar values are equal.
|
|
8
|
+
*
|
|
9
|
+
* For float and double, values are compared following IEEE semantics: -0
|
|
10
|
+
* equals 0, and NaN does not equal NaN. This is value equality, not identity.
|
|
11
|
+
*
|
|
12
|
+
* It deliberately differs from isScalarZeroValue, which treats -0 as distinct
|
|
13
|
+
* from 0. A value can equal the zero value without being a zero value
|
|
14
|
+
* (scalarEquals(DOUBLE, -0, 0) is true while isScalarZeroValue(DOUBLE, -0) is
|
|
15
|
+
* false) so this function must not be used to derive implicit presence.
|
|
8
16
|
*/
|
|
9
17
|
export declare function scalarEquals(type: ScalarType, a: ScalarValue | undefined, b: ScalarValue | undefined): boolean;
|
|
10
18
|
/**
|
|
11
|
-
* Returns the zero value for the given scalar type
|
|
19
|
+
* Returns the zero value for the given scalar type, the value a field of this
|
|
20
|
+
* type has when unset: 0 for numeric types, "" for strings, false for
|
|
21
|
+
* booleans, and an empty Uint8Array for bytes. For 64-bit integer types, the
|
|
22
|
+
* result is "0" when longAsString is true, otherwise 0n.
|
|
23
|
+
*
|
|
24
|
+
* This is the type's zero value, not a proto2 custom field default. For float
|
|
25
|
+
* and double it is +0; isScalarZeroValue treats only +0, not -0, as this value.
|
|
12
26
|
*/
|
|
13
27
|
export declare function scalarZeroValue<T extends ScalarType, LongAsString extends boolean>(type: T, longAsString: LongAsString): ScalarValue<T, LongAsString>;
|
|
14
28
|
/**
|
|
15
|
-
* Returns true
|
|
16
|
-
*
|
|
29
|
+
* Returns true if the value is the zero value for the given scalar type: `0`
|
|
30
|
+
* for numeric types, `false` for booleans, `""` for strings, and an empty
|
|
31
|
+
* Uint8Array for bytes.
|
|
32
|
+
*
|
|
33
|
+
* This is the implicit-presence default check. A singular field with implicit
|
|
34
|
+
* presence is treated as unset, and omitted from the wire, when its value is
|
|
35
|
+
* the zero value. With explicit presence, or in repeated and map fields,
|
|
36
|
+
* presence is structural and this function does not apply.
|
|
17
37
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
38
|
+
* Note that -0 is NOT a zero value for float and double: under implicit
|
|
39
|
+
* presence, +0 is omitted from the wire but -0 is written, following the
|
|
40
|
+
* proto3 specification. As a result this can disagree with scalarEquals, which
|
|
41
|
+
* compares by value and treats -0 as equal to 0.
|
|
20
42
|
*/
|
|
21
43
|
export declare function isScalarZeroValue(type: ScalarType, value: unknown): boolean;
|
|
@@ -15,6 +15,14 @@ import { protoInt64 } from "../proto-int64.js";
|
|
|
15
15
|
import { ScalarType } from "../descriptors.js";
|
|
16
16
|
/**
|
|
17
17
|
* Returns true if both scalar values are equal.
|
|
18
|
+
*
|
|
19
|
+
* For float and double, values are compared following IEEE semantics: -0
|
|
20
|
+
* equals 0, and NaN does not equal NaN. This is value equality, not identity.
|
|
21
|
+
*
|
|
22
|
+
* It deliberately differs from isScalarZeroValue, which treats -0 as distinct
|
|
23
|
+
* from 0. A value can equal the zero value without being a zero value
|
|
24
|
+
* (scalarEquals(DOUBLE, -0, 0) is true while isScalarZeroValue(DOUBLE, -0) is
|
|
25
|
+
* false) so this function must not be used to derive implicit presence.
|
|
18
26
|
*/
|
|
19
27
|
export function scalarEquals(type, a, b) {
|
|
20
28
|
if (a === b) {
|
|
@@ -51,7 +59,13 @@ export function scalarEquals(type, a, b) {
|
|
|
51
59
|
return false;
|
|
52
60
|
}
|
|
53
61
|
/**
|
|
54
|
-
* Returns the zero value for the given scalar type
|
|
62
|
+
* Returns the zero value for the given scalar type, the value a field of this
|
|
63
|
+
* type has when unset: 0 for numeric types, "" for strings, false for
|
|
64
|
+
* booleans, and an empty Uint8Array for bytes. For 64-bit integer types, the
|
|
65
|
+
* result is "0" when longAsString is true, otherwise 0n.
|
|
66
|
+
*
|
|
67
|
+
* This is the type's zero value, not a proto2 custom field default. For float
|
|
68
|
+
* and double it is +0; isScalarZeroValue treats only +0, not -0, as this value.
|
|
55
69
|
*/
|
|
56
70
|
export function scalarZeroValue(type, longAsString) {
|
|
57
71
|
switch (type) {
|
|
@@ -77,11 +91,19 @@ export function scalarZeroValue(type, longAsString) {
|
|
|
77
91
|
}
|
|
78
92
|
}
|
|
79
93
|
/**
|
|
80
|
-
* Returns true
|
|
81
|
-
*
|
|
94
|
+
* Returns true if the value is the zero value for the given scalar type: `0`
|
|
95
|
+
* for numeric types, `false` for booleans, `""` for strings, and an empty
|
|
96
|
+
* Uint8Array for bytes.
|
|
82
97
|
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
98
|
+
* This is the implicit-presence default check. A singular field with implicit
|
|
99
|
+
* presence is treated as unset, and omitted from the wire, when its value is
|
|
100
|
+
* the zero value. With explicit presence, or in repeated and map fields,
|
|
101
|
+
* presence is structural and this function does not apply.
|
|
102
|
+
*
|
|
103
|
+
* Note that -0 is NOT a zero value for float and double: under implicit
|
|
104
|
+
* presence, +0 is omitted from the wire but -0 is written, following the
|
|
105
|
+
* proto3 specification. As a result this can disagree with scalarEquals, which
|
|
106
|
+
* compares by value and treats -0 as equal to 0.
|
|
85
107
|
*/
|
|
86
108
|
export function isScalarZeroValue(type, value) {
|
|
87
109
|
switch (type) {
|
|
@@ -91,7 +113,12 @@ export function isScalarZeroValue(type, value) {
|
|
|
91
113
|
return value === "";
|
|
92
114
|
case ScalarType.BYTES:
|
|
93
115
|
return value instanceof Uint8Array && !value.byteLength;
|
|
116
|
+
case ScalarType.DOUBLE:
|
|
117
|
+
case ScalarType.FLOAT:
|
|
118
|
+
// Object.is distinguishes -0 from 0.
|
|
119
|
+
return Object.is(value, 0);
|
|
94
120
|
default:
|
|
95
|
-
|
|
121
|
+
// Loose comparison matches 0n, 0 and "0".
|
|
122
|
+
return value == 0;
|
|
96
123
|
}
|
|
97
124
|
}
|