protobufjs 8.5.0 → 8.6.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.
- package/README.md +46 -57
- package/dist/light/protobuf.js +116 -35
- package/dist/light/protobuf.js.map +1 -1
- package/dist/light/protobuf.min.js +3 -3
- package/dist/light/protobuf.min.js.map +1 -1
- package/dist/minimal/protobuf.js +3 -3
- package/dist/minimal/protobuf.js.map +1 -1
- package/dist/minimal/protobuf.min.js +3 -3
- package/dist/minimal/protobuf.min.js.map +1 -1
- package/dist/protobuf.js +131 -36
- package/dist/protobuf.js.map +1 -1
- package/dist/protobuf.min.js +3 -3
- package/dist/protobuf.min.js.map +1 -1
- package/ext/README.md +38 -49
- package/ext/descriptor.generated.d.ts +2 -2
- package/ext/descriptor.js +18 -3
- package/ext/protojson.LICENSE +201 -0
- package/ext/protojson.d.ts +20 -0
- package/ext/protojson.generated.d.ts +49 -0
- package/ext/protojson.js +903 -0
- package/ext/textformat.d.ts +2 -2
- package/ext/textformat.generated.d.ts +22 -0
- package/ext/textformat.js +40 -19
- package/index.d.ts +26 -0
- package/package.json +2 -6
- package/src/converter.js +3 -3
- package/src/decoder.js +2 -2
- package/src/encoder.js +1 -1
- package/src/field.js +49 -7
- package/src/mapfield.js +16 -7
- package/src/parse.js +15 -1
- package/src/service.js +5 -7
- package/src/type.js +12 -3
- package/src/util/minimal.js +1 -1
- package/src/util.js +23 -0
- package/src/verifier.js +2 -2
- package/scripts/postinstall.js +0 -32
package/README.md
CHANGED
|
@@ -9,13 +9,9 @@
|
|
|
9
9
|
|
|
10
10
|
**Protocol Buffers** are a language-neutral, platform-neutral, extensible way of serializing structured data for use in communications protocols, data storage, and more, originally designed at Google ([see](https://protobuf.dev/)).
|
|
11
11
|
|
|
12
|
-
**protobuf.js** is a standalone JavaScript implementation of Protocol Buffers for Node.js and
|
|
12
|
+
**protobuf.js** is a standalone JavaScript implementation of Protocol Buffers for Node.js and browsers. It is tuned for fast binary I/O, battle-tested at scale, can load `.proto` files directly, and supports runtime reflection as well as static code generation with strong TypeScript declarations.
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
protobuf.js has grown from a personal project into a widely used JavaScript infrastructure library for Protocol Buffers. It is independently maintained, with participation from the upstream Protocol Buffers ecosystem, and is intentionally not tied to any specific vendor platform, commercial service, or schema registry.
|
|
17
|
-
|
|
18
|
-
If protobuf.js is important to your project or organization, especially if you depend on it commercially, [consider supporting](https://github.com/sponsors/dcodeIO) its ongoing maintenance.
|
|
14
|
+
If protobuf.js is important to your project or organization, especially if you depend on it commercially, [consider supporting its ongoing maintenance](https://github.com/sponsors/dcodeIO).
|
|
19
15
|
|
|
20
16
|
## Getting started
|
|
21
17
|
|
|
@@ -31,34 +27,11 @@ The [command line utility](./cli/#readme) for generating reflection bundles, sta
|
|
|
31
27
|
npm install --save-dev protobufjs-cli
|
|
32
28
|
```
|
|
33
29
|
|
|
34
|
-
The CLI is a
|
|
35
|
-
|
|
36
|
-
### Choose a runtime
|
|
37
|
-
|
|
38
|
-
Pick the smallest runtime variant that supports how your application loads schemas and whether it needs reflection at runtime.
|
|
30
|
+
The CLI is a JS-native protobuf.js toolchain that does not require setting up `protoc`. If you prefer a `protoc`-based workflow, it provides `protoc-gen-pbjs` as an option.
|
|
39
31
|
|
|
40
|
-
|
|
41
|
-
| ----------------------- | ------------------ | --------
|
|
42
|
-
| `protobufjs` | Reflection, Parser | You load `.proto` files at runtime
|
|
43
|
-
| `protobufjs/light.js` | Reflection | You load JSON bundles or build schemas programmatically
|
|
44
|
-
| `protobufjs/minimal.js` | Static runtime | You use generated static code
|
|
45
|
-
|
|
46
|
-
The full build includes the light build, and the light build includes the minimal runtime.
|
|
47
|
-
|
|
48
|
-
### Browser builds
|
|
49
|
-
|
|
50
|
-
Pick the distribution matching your runtime variant and pin an exact version:
|
|
51
|
-
|
|
52
|
-
```html
|
|
53
|
-
<!-- Full -->
|
|
54
|
-
<script src="https://cdn.jsdelivr.net/npm/protobufjs@8.X.X/dist/protobuf.min.js"></script>
|
|
55
|
-
<!-- Light -->
|
|
56
|
-
<script src="https://cdn.jsdelivr.net/npm/protobufjs@8.X.X/dist/light/protobuf.min.js"></script>
|
|
57
|
-
<!-- Minimal -->
|
|
58
|
-
<script src="https://cdn.jsdelivr.net/npm/protobufjs@8.X.X/dist/minimal/protobuf.min.js"></script>
|
|
59
|
-
```
|
|
32
|
+
#### Browser builds
|
|
60
33
|
|
|
61
|
-
|
|
34
|
+
Canonical browser builds for each runtime variant are [provided via the jsDelivr CDN](https://cdn.jsdelivr.net/npm/protobufjs@8.X.X/dist/), supporting CommonJS, AMD and global `window.protobuf`. Make sure to pin an exact version in production.
|
|
62
35
|
|
|
63
36
|
## Usage
|
|
64
37
|
|
|
@@ -92,10 +65,6 @@ Optionally use `load()` with a callback, or `loadSync()` for synchronous loading
|
|
|
92
65
|
```ts
|
|
93
66
|
const payload = { awesomeField: "hello" };
|
|
94
67
|
|
|
95
|
-
// Optionally verify if the payload is of uncertain shape
|
|
96
|
-
const err = AwesomeMessage.verify(payload);
|
|
97
|
-
if (err) throw Error(err);
|
|
98
|
-
|
|
99
68
|
// Optionally create a message instance from already valid data
|
|
100
69
|
const message = AwesomeMessage.create(payload);
|
|
101
70
|
|
|
@@ -103,11 +72,11 @@ const encoded = AwesomeMessage.encode(message).finish();
|
|
|
103
72
|
const decoded = AwesomeMessage.decode(encoded);
|
|
104
73
|
```
|
|
105
74
|
|
|
106
|
-
`encode` expects a message instance or equivalent plain object and does not verify input implicitly. Use `
|
|
75
|
+
`encode` expects a message instance or equivalent plain object and does not verify input implicitly. Use `create` to create a message instance from already valid data when useful, `verify` for plain objects whose shape is not guaranteed, and `fromObject` when conversion from broader JavaScript objects is needed.
|
|
107
76
|
|
|
108
|
-
Plain objects can be encoded directly when they already use protobuf.js runtime types: numbers for 32-bit numeric fields, booleans for `bool`, strings for `string`, `Uint8Array` or `Buffer` for `bytes`, arrays for repeated fields, and plain objects for maps. Map keys are the string representation of the respective value or an 8-character hash string for 64-bit
|
|
77
|
+
Plain objects can be encoded directly when they already use protobuf.js runtime types: numbers for 32-bit numeric fields, booleans for `bool`, strings for `string`, `Uint8Array` or `Buffer` for `bytes`, arrays for repeated fields, and plain objects for maps. Map keys are the string representation of the respective value or an 8-character hash string for 64-bit keys.
|
|
109
78
|
|
|
110
|
-
Unknown fields present on the wire are preserved by default in `message.$unknowns` and forwarded when the message is re-encoded. Unknown field data can be dropped from a decoded message with `delete message.$unknowns`, discarded during decode
|
|
79
|
+
Unknown fields present on the wire are preserved by default in `message.$unknowns` and forwarded when the message is re-encoded. Unknown field data can be dropped from a decoded message with `delete message.$unknowns`, discarded during decode with `reader.discardUnknown = true` per reader, or disabled by default for subsequently created readers with `Reader.discardUnknown = true`.
|
|
111
80
|
|
|
112
81
|
### Convert plain objects
|
|
113
82
|
|
|
@@ -164,7 +133,7 @@ Message types expose focused methods for validation, conversion, and binary I/O.
|
|
|
164
133
|
* **toObject**(message: `Message`, options?: `ConversionOptions`): `object`
|
|
165
134
|
Converts a message instance to a configurable plain JavaScript object.
|
|
166
135
|
|
|
167
|
-
* **message
|
|
136
|
+
* **message.toJSON**(): `object`
|
|
168
137
|
Converts a message instance to JSON-compatible output using default conversion options.
|
|
169
138
|
|
|
170
139
|
Message instances provide runtime identity, so they can be tested with `instanceof`. Their `toJSON` method integrates them with `JSON.stringify`.
|
|
@@ -173,9 +142,21 @@ Length-delimited methods read and write a varint byte length before the message,
|
|
|
173
142
|
|
|
174
143
|
If required fields are missing while decoding proto2 data, `decode` throws `protobuf.util.ProtocolError` with the partially decoded message available as `err.instance`.
|
|
175
144
|
|
|
145
|
+
## Runtimes
|
|
146
|
+
|
|
147
|
+
protobuf.js provides three runtime entry points, keeping parser and reflection support optional: Runtime `.proto` loading needs the parser, JSON/reflection bundles need reflection support, and generated static modules only need the minimal runtime.
|
|
148
|
+
|
|
149
|
+
| Import | Includes | Use when
|
|
150
|
+
| ----------------------- | ------------------ | --------
|
|
151
|
+
| `protobufjs` | Reflection, Parser | You load `.proto` files at runtime
|
|
152
|
+
| `protobufjs/light.js` | Reflection | You load JSON bundles or build schemas programmatically
|
|
153
|
+
| `protobufjs/minimal.js` | Static runtime | You use generated static code
|
|
154
|
+
|
|
155
|
+
The full build includes the light build, and the light build includes the minimal runtime.
|
|
156
|
+
|
|
176
157
|
## Code generation
|
|
177
158
|
|
|
178
|
-
|
|
159
|
+
Use [`protobufjs-cli`](./cli/#readme) to generate reflection bundles, static JavaScript code, and matching TypeScript declarations, either directly with `pbjs` or through the optional `protoc-gen-pbjs` plugin for `protoc`.
|
|
179
160
|
|
|
180
161
|
Reflection keeps schemas as JSON metadata and generates optimized functions at runtime. Static code emits schema-specific, reflection-free functions ahead of time. The main tradeoffs are how schemas are loaded, how bundle size scales with schema size, and whether reflection metadata should remain available at runtime.
|
|
181
162
|
|
|
@@ -201,9 +182,11 @@ import { awesomepackage } from "./awesome.js";
|
|
|
201
182
|
const message = awesomepackage.AwesomeMessage.create({ awesomeField: "hello" });
|
|
202
183
|
```
|
|
203
184
|
|
|
185
|
+
While static code is verbose by design, its repeated patterns compress well with Brotli or gzip, and it works in [CSP](https://w3c.github.io/webappsec-csp/)-restricted environments that disallow unsafe-eval without sacrificing performance.
|
|
186
|
+
|
|
204
187
|
### Reflection bundles
|
|
205
188
|
|
|
206
|
-
|
|
189
|
+
Reflection bundles store schemas as compact JSON metadata, avoiding `.proto` parsing at runtime and letting browsers load schema metadata in one request. While they require at least `protobufjs/light.js`, large schemas can produce smaller combined bundles than equivalent static modules because common code is shared through reflection.
|
|
207
190
|
|
|
208
191
|
```sh
|
|
209
192
|
npx pbjs -t json -o awesome.json awesome1.proto awesome2.proto ...
|
|
@@ -331,33 +314,39 @@ const myService = MyService.create(myRpcImpl/*, requestDelimited?, responseDelim
|
|
|
331
314
|
|
|
332
315
|
See [examples/streaming-rpc.js](./examples/streaming-rpc.js) for a streaming example.
|
|
333
316
|
|
|
334
|
-
###
|
|
317
|
+
### Extensions
|
|
335
318
|
|
|
336
|
-
|
|
319
|
+
The following extensions provide descriptor conversion and text-based protobuf formats when reflection metadata is available. Most applications only need the binary APIs above.
|
|
337
320
|
|
|
338
|
-
|
|
321
|
+
#### Descriptors
|
|
339
322
|
|
|
340
|
-
|
|
323
|
+
protobuf.js uses a compact JSON-based reflection representation internally that is easy to embed and fast to parse, so schemas can be loaded directly without first decoding binary descriptor blobs or postprocessing their full JSON representation. See [ext/descriptor](./ext/README.md#descriptor) for use cases that need conversion between reflected roots and `protoc` descriptor messages.
|
|
341
324
|
|
|
342
|
-
|
|
325
|
+
#### ProtoJSON
|
|
343
326
|
|
|
344
|
-
|
|
327
|
+
Protocol Buffers support a special [ProtoJSON format](https://protobuf.dev/programming-guides/json/) to share data with systems that do not support the binary wire format, for example when implementing gateways. Spec-compliant ProtoJSON is supported via [ext/protojson](./ext/README.md#protojson).
|
|
345
328
|
|
|
346
|
-
|
|
329
|
+
#### Text Format
|
|
330
|
+
|
|
331
|
+
Protocol Buffers [Text Format](https://protobuf.dev/reference/protobuf/textformat-spec/) is a special syntax for representing protobuf data in text form, which can be useful for configurations or tests. Spec-compliant Text Format is supported via [ext/textformat](./ext/README.md#textformat).
|
|
347
332
|
|
|
348
|
-
|
|
333
|
+
## Conformance
|
|
349
334
|
|
|
350
|
-
|
|
335
|
+
protobuf.js targets complete binary wire-format conformance for **Proto2**, **Proto3** and **Editions** in both static and reflection modes, plus complete **ProtoJSON** and **Text Format** conformance with reflection metadata present. CI runs the official Protocol Buffers conformance suite for validation, with logs [uploaded as artifacts](https://github.com/protobufjs/protobuf.js/actions/workflows/test.yml?query=branch%3Amaster+event%3Apush).
|
|
351
336
|
|
|
352
|
-
|
|
|
353
|
-
|
|
|
354
|
-
|
|
|
355
|
-
|
|
|
356
|
-
|
|
|
337
|
+
| Category | Total | Required | Recommended |
|
|
338
|
+
| ---------- | ------------------: | ------------------: | ------------------: |
|
|
339
|
+
| Binary | 100.00% (2805/2805) | 100.00% (1939/1939) | 100.00% (866/866) |
|
|
340
|
+
| ↳ Proto2 | 100.00% (703/703) | 100.00% (485/485) | 100.00% (218/218) |
|
|
341
|
+
| ↳ Proto3 | 100.00% (698/698) | 100.00% (482/482) | 100.00% (216/216) |
|
|
342
|
+
| ↳ Editions | 100.00% (1404/1404) | 100.00% (972/972) | 100.00% (432/432) |
|
|
343
|
+
| ProtoJSON | 100.00% (2762/2762) | 100.00% (2328/2328) | 100.00% (434/434) |
|
|
344
|
+
| TextFormat | 100.00% (883/883) | 100.00% (819/819) | 100.00% (64/64) |
|
|
345
|
+
| Overall | 100.00% (6450/6450) | 100.00% (5086/5086) | 100.00% (1364/1364) |
|
|
357
346
|
|
|
358
347
|
## Performance
|
|
359
348
|
|
|
360
|
-
In both reflection and
|
|
349
|
+
In both reflection and reflection-free modes, protobuf.js builds specialized encoders and decoders instead of interpreting descriptors at runtime.
|
|
361
350
|
|
|
362
351
|
The repository includes a [small benchmark](./bench). It compares protobuf.js reflection and static code against JSON encode/decode, protoc-gen-js, and protoc-gen-es. Results depend on hardware, Node.js version, and message shape, so they should be treated as indicative rather than absolute.
|
|
363
352
|
|
package/dist/light/protobuf.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* protobuf.js v8.
|
|
3
|
-
* compiled
|
|
2
|
+
* protobuf.js v8.6.0 (c) 2016, daniel wirtz
|
|
3
|
+
* compiled thu, 04 jun 2026 21:47:14 utc
|
|
4
4
|
* licensed under the bsd-3-clause license
|
|
5
5
|
* see: https://github.com/dcodeio/protobuf.js for details
|
|
6
6
|
*/
|
|
@@ -148,7 +148,7 @@ function genValuePartial_fromObject(gen, field, fieldIndex, prop) {
|
|
|
148
148
|
converter.fromObject = function fromObject(mtype) {
|
|
149
149
|
/* eslint-disable no-unexpected-multiline, block-scoped-var, no-redeclare */
|
|
150
150
|
var fields = mtype.fieldsArray;
|
|
151
|
-
var gen = util.codegen(["d", "q"]
|
|
151
|
+
var gen = util.codegen(["d", "q"])
|
|
152
152
|
("if(d instanceof C)")
|
|
153
153
|
("return d")
|
|
154
154
|
("if(!util.isObject(d))")
|
|
@@ -282,7 +282,7 @@ converter.toObject = function toObject(mtype) {
|
|
|
282
282
|
var fields = mtype.fieldsArray.slice().sort(util.compareFieldsById);
|
|
283
283
|
if (!fields.length)
|
|
284
284
|
return util.codegen()("return {}");
|
|
285
|
-
var gen = util.codegen(["m", "o", "q"]
|
|
285
|
+
var gen = util.codegen(["m", "o", "q"])
|
|
286
286
|
("if(!o)")
|
|
287
287
|
("o={}")
|
|
288
288
|
("if(q===undefined)q=0")
|
|
@@ -371,7 +371,7 @@ converter.toObject = function toObject(mtype) {
|
|
|
371
371
|
genValuePartial_toObject(gen, field, /* sorted */ index, prop + "[j]")
|
|
372
372
|
("}");
|
|
373
373
|
} else { gen
|
|
374
|
-
("if(m%s!=null&&
|
|
374
|
+
("if(m%s!=null&&Object.hasOwnProperty.call(m,%j)){", prop, field.name); // !== undefined && !== null
|
|
375
375
|
genValuePartial_toObject(gen, field, /* sorted */ index, prop);
|
|
376
376
|
if (field.partOf && !field.partOf.isProto3Optional) gen
|
|
377
377
|
("if(o.oneofs)")
|
|
@@ -414,7 +414,7 @@ function decoder(mtype) {
|
|
|
414
414
|
if (!pfield.repeated && !pfield.map && !pfield.hasPresence)
|
|
415
415
|
hasImplicitPresenceField = true;
|
|
416
416
|
}
|
|
417
|
-
var gen = util.codegen(["r", "l", "z", "q", "g"]
|
|
417
|
+
var gen = util.codegen(["r", "l", "z", "q", "g"])
|
|
418
418
|
("if(!(r instanceof Reader))")
|
|
419
419
|
("r=Reader.create(r)")
|
|
420
420
|
("if(q===undefined)q=0")
|
|
@@ -586,7 +586,7 @@ function decoder(mtype) {
|
|
|
586
586
|
for (i = 0; i < mtype._fieldsArray.length; ++i) {
|
|
587
587
|
var rfield = mtype._fieldsArray[i];
|
|
588
588
|
if (rfield.required) gen
|
|
589
|
-
("if(!
|
|
589
|
+
("if(!Object.hasOwnProperty.call(m,%j))", rfield.name)
|
|
590
590
|
("throw util.ProtocolError(%j,{instance:m})", missing(rfield));
|
|
591
591
|
}
|
|
592
592
|
|
|
@@ -625,7 +625,7 @@ function genTypePartial(gen, field, fieldIndex, ref) {
|
|
|
625
625
|
*/
|
|
626
626
|
function encoder(mtype) {
|
|
627
627
|
/* eslint-disable no-unexpected-multiline, block-scoped-var, no-redeclare */
|
|
628
|
-
var gen = util.codegen(["m", "w", "q"]
|
|
628
|
+
var gen = util.codegen(["m", "w", "q"])
|
|
629
629
|
("if(!w)")
|
|
630
630
|
("w=Writer.create()")
|
|
631
631
|
("if(q===undefined)q=0")
|
|
@@ -982,6 +982,12 @@ Field.fromJSON = function fromJSON(name, json) {
|
|
|
982
982
|
var field = new Field(name, json.id, json.type, json.rule, json.extend, json.options, json.comment);
|
|
983
983
|
if (json.edition)
|
|
984
984
|
field._edition = json.edition;
|
|
985
|
+
if (json.protoName)
|
|
986
|
+
field.protoName = json.protoName;
|
|
987
|
+
if (json.jsonName !== undefined)
|
|
988
|
+
field.jsonName = json.jsonName;
|
|
989
|
+
else if (json.options && json.options.json_name !== undefined)
|
|
990
|
+
field.jsonName = json.options.json_name;
|
|
985
991
|
field._defaultEdition = "proto3"; // For backwards-compatibility.
|
|
986
992
|
return field;
|
|
987
993
|
};
|
|
@@ -1121,6 +1127,18 @@ function Field(name, id, type, rule, extend, options, comment) {
|
|
|
1121
1127
|
* @type {string|null}
|
|
1122
1128
|
*/
|
|
1123
1129
|
this.comment = comment;
|
|
1130
|
+
|
|
1131
|
+
/**
|
|
1132
|
+
* Field name as declared in the .proto source, if different from `name`.
|
|
1133
|
+
* @type {string|undefined}
|
|
1134
|
+
*/
|
|
1135
|
+
this.protoName = undefined;
|
|
1136
|
+
|
|
1137
|
+
/**
|
|
1138
|
+
* JSON name, if different from the derived default.
|
|
1139
|
+
* @type {string|undefined}
|
|
1140
|
+
*/
|
|
1141
|
+
this.jsonName = undefined;
|
|
1124
1142
|
}
|
|
1125
1143
|
|
|
1126
1144
|
/**
|
|
@@ -1190,6 +1208,22 @@ Object.defineProperty(Field.prototype, "hasPresence", {
|
|
|
1190
1208
|
}
|
|
1191
1209
|
});
|
|
1192
1210
|
|
|
1211
|
+
/**
|
|
1212
|
+
* The field name as declared in the .proto source (snake_case). Populated on resolve,
|
|
1213
|
+
* falling back to `name`. Mirrors `FieldDescriptorProto.name`.
|
|
1214
|
+
* @name Field#protoName
|
|
1215
|
+
* @type {string}
|
|
1216
|
+
* @readonly
|
|
1217
|
+
*/
|
|
1218
|
+
|
|
1219
|
+
/**
|
|
1220
|
+
* The JSON name of this field (lowerCamelCase per protoc's `ToJsonName`, or an
|
|
1221
|
+
* explicit `[json_name]`). Populated on resolve. This is the key used on ProtoJSON output.
|
|
1222
|
+
* @name Field#jsonName
|
|
1223
|
+
* @type {string}
|
|
1224
|
+
* @readonly
|
|
1225
|
+
*/
|
|
1226
|
+
|
|
1193
1227
|
/**
|
|
1194
1228
|
* @override
|
|
1195
1229
|
*/
|
|
@@ -1223,13 +1257,15 @@ Field.prototype.setOption = function setOption(name, value, ifNotSet) {
|
|
|
1223
1257
|
Field.prototype.toJSON = function toJSON(toJSONOptions) {
|
|
1224
1258
|
var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
|
|
1225
1259
|
return util.toObject([
|
|
1226
|
-
"edition"
|
|
1227
|
-
"rule"
|
|
1228
|
-
"type"
|
|
1229
|
-
"id"
|
|
1230
|
-
"extend"
|
|
1231
|
-
"
|
|
1232
|
-
"
|
|
1260
|
+
"edition" , this._editionToJSON(),
|
|
1261
|
+
"rule" , this.rule !== "optional" && this.rule || undefined,
|
|
1262
|
+
"type" , this.type,
|
|
1263
|
+
"id" , this.id,
|
|
1264
|
+
"extend" , this.extend,
|
|
1265
|
+
"protoName" , this.protoName !== this.name ? this.protoName : undefined,
|
|
1266
|
+
"jsonName" , this.jsonName !== util.jsonName(this.protoName || this.name) ? this.jsonName : undefined,
|
|
1267
|
+
"options" , this.options,
|
|
1268
|
+
"comment" , keepComments ? this.comment : undefined
|
|
1233
1269
|
]);
|
|
1234
1270
|
};
|
|
1235
1271
|
|
|
@@ -1298,6 +1334,12 @@ Field.prototype.resolve = function resolve() {
|
|
|
1298
1334
|
if (this.parent instanceof Type && this.parent._ctor)
|
|
1299
1335
|
this.parent._ctor.prototype[this.name] = this.defaultValue;
|
|
1300
1336
|
|
|
1337
|
+
// derive the proto/JSON names
|
|
1338
|
+
if (this.protoName === undefined)
|
|
1339
|
+
this.protoName = this.name;
|
|
1340
|
+
if (this.jsonName === undefined)
|
|
1341
|
+
this.jsonName = util.jsonName(this.protoName);
|
|
1342
|
+
|
|
1301
1343
|
return ReflectionObject.prototype.resolve.call(this);
|
|
1302
1344
|
};
|
|
1303
1345
|
|
|
@@ -1610,7 +1652,14 @@ function MapField(name, id, keyType, type, options, comment) {
|
|
|
1610
1652
|
* @throws {TypeError} If arguments are invalid
|
|
1611
1653
|
*/
|
|
1612
1654
|
MapField.fromJSON = function fromJSON(name, json) {
|
|
1613
|
-
|
|
1655
|
+
var field = new MapField(name, json.id, json.keyType, json.type, json.options, json.comment);
|
|
1656
|
+
if (json.protoName)
|
|
1657
|
+
field.protoName = json.protoName;
|
|
1658
|
+
if (json.jsonName !== undefined)
|
|
1659
|
+
field.jsonName = json.jsonName;
|
|
1660
|
+
else if (json.options && json.options.json_name !== undefined)
|
|
1661
|
+
field.jsonName = json.options.json_name;
|
|
1662
|
+
return field;
|
|
1614
1663
|
};
|
|
1615
1664
|
|
|
1616
1665
|
/**
|
|
@@ -1621,12 +1670,14 @@ MapField.fromJSON = function fromJSON(name, json) {
|
|
|
1621
1670
|
MapField.prototype.toJSON = function toJSON(toJSONOptions) {
|
|
1622
1671
|
var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
|
|
1623
1672
|
return util.toObject([
|
|
1624
|
-
"keyType"
|
|
1625
|
-
"type"
|
|
1626
|
-
"id"
|
|
1627
|
-
"extend"
|
|
1628
|
-
"
|
|
1629
|
-
"
|
|
1673
|
+
"keyType" , this.keyType,
|
|
1674
|
+
"type" , this.type,
|
|
1675
|
+
"id" , this.id,
|
|
1676
|
+
"extend" , this.extend,
|
|
1677
|
+
"protoName" , this.protoName !== this.name ? this.protoName : undefined,
|
|
1678
|
+
"jsonName" , this.jsonName !== util.jsonName(this.protoName || this.name) ? this.jsonName : undefined,
|
|
1679
|
+
"options" , this.options,
|
|
1680
|
+
"comment" , keepComments ? this.comment : undefined
|
|
1630
1681
|
]);
|
|
1631
1682
|
};
|
|
1632
1683
|
|
|
@@ -4422,8 +4473,6 @@ var Method = require(11),
|
|
|
4422
4473
|
util = require(24),
|
|
4423
4474
|
rpc = require(19);
|
|
4424
4475
|
|
|
4425
|
-
var reservedRe = util.patterns.reservedRe;
|
|
4426
|
-
|
|
4427
4476
|
/**
|
|
4428
4477
|
* Constructs a new service instance.
|
|
4429
4478
|
* @classdesc Reflected service.
|
|
@@ -4603,11 +4652,11 @@ Service.prototype.create = function create(rpcImpl, requestDelimited, responseDe
|
|
|
4603
4652
|
var rpcService = new rpc.Service(rpcImpl, requestDelimited, responseDelimited);
|
|
4604
4653
|
for (var i = 0, method; i < /* initializes */ this.methodsArray.length; ++i) {
|
|
4605
4654
|
var methodName = util.lcFirst((method = this._methodsArray[i]).resolve().name).replace(/[^$\w_]/g, "");
|
|
4606
|
-
rpcService[methodName] =
|
|
4607
|
-
|
|
4608
|
-
|
|
4609
|
-
|
|
4610
|
-
});
|
|
4655
|
+
rpcService[methodName] = (function(method, requestType, responseType) {
|
|
4656
|
+
return function rpcMethod(request, callback) {
|
|
4657
|
+
return rpc.Service.prototype.rpcCall.call(this, method, requestType, responseType, request, callback);
|
|
4658
|
+
};
|
|
4659
|
+
})(method, method.resolvedRequestType.ctor, method.resolvedResponseType.ctor);
|
|
4611
4660
|
}
|
|
4612
4661
|
return rpcService;
|
|
4613
4662
|
};
|
|
@@ -4704,6 +4753,13 @@ function Type(name, options) {
|
|
|
4704
4753
|
* @private
|
|
4705
4754
|
*/
|
|
4706
4755
|
this._ctor = null;
|
|
4756
|
+
|
|
4757
|
+
/**
|
|
4758
|
+
* Cached fields by JSON name.
|
|
4759
|
+
* @type {Object.<string,Field>|null}
|
|
4760
|
+
* @private
|
|
4761
|
+
*/
|
|
4762
|
+
this._fieldsByJsonName = null; // used by ext/protojson
|
|
4707
4763
|
}
|
|
4708
4764
|
|
|
4709
4765
|
Object.defineProperties(Type.prototype, {
|
|
@@ -4816,7 +4872,7 @@ Object.defineProperties(Type.prototype, {
|
|
|
4816
4872
|
*/
|
|
4817
4873
|
Type.generateConstructor = function generateConstructor(mtype) {
|
|
4818
4874
|
/* eslint-disable no-unexpected-multiline */
|
|
4819
|
-
var gen = util.codegen(["p"]
|
|
4875
|
+
var gen = util.codegen(["p"]);
|
|
4820
4876
|
// explicitly initialize mutable object/array fields so that these aren't just inherited from the prototype
|
|
4821
4877
|
for (var i = 0, field; i < mtype.fieldsArray.length; ++i)
|
|
4822
4878
|
if ((field = mtype._fieldsArray[i]).map) gen
|
|
@@ -4830,7 +4886,7 @@ Type.generateConstructor = function generateConstructor(mtype) {
|
|
|
4830
4886
|
};
|
|
4831
4887
|
|
|
4832
4888
|
function clearCache(type) {
|
|
4833
|
-
type._fieldsById = type._fieldsArray = type._oneofsArray = null;
|
|
4889
|
+
type._fieldsById = type._fieldsArray = type._oneofsArray = type._fieldsByJsonName = null;
|
|
4834
4890
|
delete type.encode;
|
|
4835
4891
|
delete type.decode;
|
|
4836
4892
|
delete type.verify;
|
|
@@ -4994,7 +5050,7 @@ Type.prototype.add = function add(object) {
|
|
|
4994
5050
|
throw Error("duplicate id " + object.id + " in " + this);
|
|
4995
5051
|
if (this.isReservedId(object.id))
|
|
4996
5052
|
throw Error("id " + object.id + " is reserved in " + this);
|
|
4997
|
-
if (this.isReservedName(object.name))
|
|
5053
|
+
if (this.isReservedName(object.name) || object.name.charAt(0) === "$")
|
|
4998
5054
|
throw Error("name '" + object.name + "' is reserved in " + this);
|
|
4999
5055
|
if (object.name === "__proto__")
|
|
5000
5056
|
return this;
|
|
@@ -5007,6 +5063,8 @@ Type.prototype.add = function add(object) {
|
|
|
5007
5063
|
return clearCache(this);
|
|
5008
5064
|
}
|
|
5009
5065
|
if (object instanceof OneOf) {
|
|
5066
|
+
if (object.name.charAt(0) === "$")
|
|
5067
|
+
throw Error("name '" + object.name + "' is reserved in " + this);
|
|
5010
5068
|
if (object.name === "__proto__")
|
|
5011
5069
|
return this;
|
|
5012
5070
|
if (!this.oneofs)
|
|
@@ -5554,6 +5612,7 @@ var camelCaseRe = /_([a-z])/g;
|
|
|
5554
5612
|
* Converts a string to camel case.
|
|
5555
5613
|
* @param {string} str String to convert
|
|
5556
5614
|
* @returns {string} Converted string
|
|
5615
|
+
* @deprecated Use {@link util.jsonName} for protobuf field JSON names.
|
|
5557
5616
|
*/
|
|
5558
5617
|
util.camelCase = function camelCase(str) {
|
|
5559
5618
|
return str.substring(0, 1)
|
|
@@ -5561,6 +5620,28 @@ util.camelCase = function camelCase(str) {
|
|
|
5561
5620
|
.replace(camelCaseRe, function($0, $1) { return $1.toUpperCase(); });
|
|
5562
5621
|
};
|
|
5563
5622
|
|
|
5623
|
+
/**
|
|
5624
|
+
* Converts a proto field name to its protoc-compatible JSON name.
|
|
5625
|
+
* @param {string} str Proto field name
|
|
5626
|
+
* @returns {string} JSON name
|
|
5627
|
+
*/
|
|
5628
|
+
util.jsonName = function jsonName(str) {
|
|
5629
|
+
var result = "",
|
|
5630
|
+
upperNext = false,
|
|
5631
|
+
i = 0;
|
|
5632
|
+
for (; i < str.length; ++i) {
|
|
5633
|
+
var ch = str.charAt(i);
|
|
5634
|
+
if (ch === "_")
|
|
5635
|
+
upperNext = true;
|
|
5636
|
+
else if (upperNext) {
|
|
5637
|
+
result += ch.toUpperCase();
|
|
5638
|
+
upperNext = false;
|
|
5639
|
+
} else
|
|
5640
|
+
result += ch;
|
|
5641
|
+
}
|
|
5642
|
+
return result;
|
|
5643
|
+
};
|
|
5644
|
+
|
|
5564
5645
|
/**
|
|
5565
5646
|
* Compares reflected fields by id.
|
|
5566
5647
|
* @param {Field} a First field
|
|
@@ -6912,7 +6993,7 @@ util.isset =
|
|
|
6912
6993
|
*/
|
|
6913
6994
|
util.isSet = function isSet(obj, prop) {
|
|
6914
6995
|
var value = obj[prop];
|
|
6915
|
-
if (value != null &&
|
|
6996
|
+
if (value != null && Object.hasOwnProperty.call(obj, prop)) // eslint-disable-line eqeqeq
|
|
6916
6997
|
return typeof value !== "object" || (Array.isArray(value) ? value.length : Object.keys(value).length) > 0;
|
|
6917
6998
|
return false;
|
|
6918
6999
|
};
|
|
@@ -7700,7 +7781,7 @@ function genVerifyKey(gen, field, ref) {
|
|
|
7700
7781
|
function verifier(mtype) {
|
|
7701
7782
|
/* eslint-disable no-unexpected-multiline */
|
|
7702
7783
|
|
|
7703
|
-
var gen = util.codegen(["m", "q"]
|
|
7784
|
+
var gen = util.codegen(["m", "q"])
|
|
7704
7785
|
("if(typeof m!==\"object\"||m===null)")
|
|
7705
7786
|
("return%j", "object expected")
|
|
7706
7787
|
("if(q===undefined)q=0")
|
|
@@ -7716,7 +7797,7 @@ function verifier(mtype) {
|
|
|
7716
7797
|
ref = "m" + util.safeProp(field.name);
|
|
7717
7798
|
|
|
7718
7799
|
if (field.optional) gen
|
|
7719
|
-
("if(%s!=null&&
|
|
7800
|
+
("if(%s!=null&&Object.hasOwnProperty.call(m,%j)){", ref, field.name); // !== undefined && !== null
|
|
7720
7801
|
|
|
7721
7802
|
// map fields
|
|
7722
7803
|
if (field.map) { gen
|