Skip to content

Commit 6cdf8a2

Browse files
authored
Merge pull request #120 from dibenede/add-docs
Add generated code docs as docs/index.md
2 parents a8b2e00 + bf0999e commit 6cdf8a2

File tree

1 file changed

+388
-0
lines changed

1 file changed

+388
-0
lines changed

docs/index.md

Lines changed: 388 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,388 @@
1+
2+
# JavaScript Generated Code
3+
4+
This page describes exactly what JavaScript code the protocol buffer compiler
5+
generates for any given protocol definition. Any differences between proto2 and
6+
proto3 generated code are highlighted. You should read the
7+
[proto2 language guide](https://developers.google.com/protocol-buffers/docs/proto) and/or the
8+
[proto3 language guide](https://developers.google.com/protocol-buffers/docs/proto3) before reading this document.
9+
10+
## Compiler Invocation
11+
The protocol buffer compiler produces JavaScript output when invoked with the
12+
`--js_out=` command-line flag. The parameter to the `--js_out=` option is the
13+
directory where you want the compiler to write your JavaScript output. The exact
14+
output depends on whether you want to use Closure-style imports or
15+
CommonJS-style imports; the compiler supports both.
16+
17+
**Note:** Support for ES6-style imports is not implemented yet. Browsers can be supported by using Browserify, webpack, Closure Compiler, or similar to resolve imports at compile time.
18+
19+
### Closure Imports
20+
By default, the compiler generates code with Closure-style imports. If you
21+
specify a `library` option when running the compiler, the compiler creates a
22+
single `.js` file with your specified library name. Otherwise the compiler
23+
generates a `.js` file for each *message* in your `.proto` file. The names of
24+
the output files are computed by taking the `library` value or message name
25+
(lowercased), with the following changes.
26+
27+
So, for example, let's say you invoke the compiler as follows:
28+
29+
```
30+
protoc --plugin=protoc-gen-js=/path/to/protobuf-javascript/bazel-bin/generator/protoc-gen-js --proto_path=src --js_out=library=whizz/ponycopter,binary:build/gen src/foo.proto src/bar/baz.proto
31+
```
32+
33+
The compiler will read the files `src/foo.proto` and `src/bar/baz.proto` and
34+
produce a single output file, `build/gen/whizz/ponycopter.js`. The compiler will
35+
automatically create the directory `build/gen/whizz` if necessary, but it will
36+
*not* create `build` or `build/gen`; they must already exist.
37+
The generated file(s) `goog.provide()` all 'the types defined in your `.proto`
38+
file(s), and `goog.require()` many types in the core protocol buffers library
39+
and Google Closure library. Make sure that your `goog.provide()` /
40+
`goog.require()` setup can find all of your generated code,
41+
[the core library `.js` files](https://github.com/protocolbuffers/protobuf-javascript)
42+
and the Google Closure library itself.
43+
44+
You should be able to import your generated types with statements like:
45+
46+
```js
47+
goog.require('proto.my.package.MyMessage');
48+
const message = proto.my.package.MyMessage();
49+
```
50+
51+
### CommonJS Imports
52+
To specify that you want to use CommonJS-style imports instead of the default
53+
Closure style, you run the compiler with the `import_style=commonjs` option. The
54+
names of the output files are computed by taking the name of the each input
55+
`.proto` file and making two changes.
56+
57+
**Note:** Specifying a `library` option is ignored with this import style.
58+
59+
So, for example, let's say you invoke the compiler as follows:
60+
61+
```
62+
protoc --plugin=protoc-gen-js=/path/to/protobuf-javascript/bazel-bin/generator/protoc-gen-js --proto_path=src --js_out=import_style=commonjs,binary:build/gen src/foo.proto src/bar/baz.proto
63+
```
64+
65+
The compiler will read the files `src/foo.proto` and `src/bar/baz.proto` and
66+
produce two output files: `build/gen/foo_pb.js` and `build/gen/bar/baz_pb.js`.
67+
The compiler will automatically create the directory `build/gen/bar` if
68+
necessary, but it will *not* create `build` or `build/gen`; they must already
69+
exist.
70+
71+
The generated code depends on the core runtime, which should be in a file
72+
called `google-protobuf.js`. If you installed protoc via `npm`, this file should
73+
already be built and available. If you are running from GitHub, you need to
74+
build it first by running:
75+
76+
```
77+
PROTOC=/path/to/protoc PROTOC_INC=/path/to/proto/include gulp dist
78+
```
79+
80+
You should be able to import your generated types with statements like:
81+
82+
```js
83+
const messages = require('./messages_pb');
84+
const message = new messages.MyMessage();
85+
```
86+
87+
### Compiler Options
88+
The protocol buffer compiler for JavaScript has many options to customize its
89+
output in addition to the `library` and `import_style` options mentioned above.
90+
For example:
91+
92+
* `binary`: Using this option generates code that lets you serialize and deserialize your proto from the protocol buffers binary wire format. We recommend that you enable this option.
93+
`--js_out=library=myprotos_lib.js,binary:.`
94+
95+
As in the above examples, multiple options can be specified, separated by commas. You can see a complete list of available options in [js_generator.h](https://github.com/protocolbuffers/protobuf-javascript/blob/59a828fc713538404dcc9de8f42b4abfcfa5eb7d/generator/js_generator.h#L62-L76).
96+
97+
## Packages
98+
### Packages and Closure Imports
99+
If you are using Closure-style imports and a `.proto` file contains a package
100+
declaration, the generated code uses the proto's `package` as part of the
101+
JavaScript namespace for your message types. For example, a proto package name
102+
of `example.high_score` results in a JavaScript namespace of `proto.example.high_score`.
103+
104+
```js
105+
goog.provide('proto.example.high_score.Ponycopter');
106+
```
107+
108+
Otherwise, if a `.proto` file does not contain a package declaration, the
109+
generated code just uses `proto` as the namespace for your message types, which
110+
is the root of the protocol buffers namespace.
111+
112+
### Packages and CommonJS Imports
113+
If you are using CommonJS-style imports, any package declarations in your
114+
`.proto` files are ignored by the compiler.
115+
116+
## Messages
117+
Given a simple message declaration:
118+
119+
```protobuf
120+
message Foo {}
121+
```
122+
123+
the protocol buffer compiler generates a class called `Foo`. `Foo` inherits
124+
from [`jspb.Message`](https://github.com/protocolbuffers/protobuf-javascript/blob/59a828fc713538404dcc9de8f42b4abfcfa5eb7d/message.js).
125+
126+
You should *not* create your own `Foo` subclasses. Generated classes are not
127+
designed for subclassing and may lead to "fragile base class" problems.
128+
129+
Your generated class has accessors for all its fields (which we'll look at in
130+
the following sections) and the following methods that apply to the entire
131+
message:
132+
133+
* `toObject()`: Returns an object representation of the message, suitable for use in Soy templates. This method comes in static and instance versions. Field names that are [reserved in JavaScript]("http://www.w3schools.com/js/js_reserved.asp") are renamed to `pb_name`. If you don't want to generate this method (for instance, if you're not going to use it and are concerned about code size), set [jspb.Message.GENERATE_TO_OBJECT](https://github.com/protocolbuffers/protobuf-javascript/blob/59a828fc713538404dcc9de8f42b4abfcfa5eb7d/message.js#L174) to false before code generation. Note that this representation is not the same as [proto3's JSON representation](https://developers.google.com/protocol-buffers/docs/proto3#json).
134+
* `clone()`: Creates a deep clone of this message and its fields.
135+
136+
The following methods are also provided if you have enabled the `binary`
137+
option when generating your code:
138+
139+
* `deserializeBinary()`: Static method. Deserializes a message from protocol buffers binary wire format and returns a new populated message object. Does not preserve any unknown fields in the binary message.
140+
* `deserializeBinaryFromReader()`: Static method. Deserializes a message in protocol buffers binary wire format from the provided [BinaryReader](https://github.com/protocolbuffers/protobuf-javascript/blob/59a828fc713538404dcc9de8f42b4abfcfa5eb7d/binary/reader.js) into the provided message object. Does not preserve any unknown fields in the binary message.
141+
* `serializeBinary()`: Serializes this message to protocol buffers binary wire format.
142+
* `serializeBinaryToWriter()`: Serializes this message in protocol buffers binary wire format to the specified [BinaryWriter](https://github.com/protocolbuffers/protobuf-javascript/blob/59a828fc713538404dcc9de8f42b4abfcfa5eb7d/binary/writer.js). This method has a static variant where you can serialize a specified message to the BinaryWriter.
143+
144+
145+
## Fields
146+
The protocol buffer compiler generates accessors for each field in your
147+
protocol buffer message. The exact accessors depend on its type and whether it
148+
is a singular, repeated, map, or oneof field.
149+
150+
Note that the generated accessors always use camel-case naming, even if the
151+
field name in the `.proto` file uses lower-case with underscores
152+
([as it should](https://developers.google.com/protocol-buffers/docs/style)). The case-conversion works as
153+
follows:
154+
155+
The proto field `foo_bar_baz` has, for example, a `getFooBarBaz()` method.
156+
157+
158+
### Singular Scalar Fields (proto2)
159+
For either of these field definitions:
160+
161+
```protobuf
162+
optional int32 foo = 1;
163+
required int32 foo = 1;
164+
```
165+
166+
the compiler generates the following instance methods:
167+
168+
* `setFoo()`: Set the value of `foo`.
169+
* `getFoo()`: Get the value of `foo`. If the field has not been set, returns the default value for its type.
170+
* `hasFoo()`: Returns `true` if this field has been set.
171+
* `clearFoo()`: Clears the value of this field: after this has been called `hasFoo()` returns `false` and `getFoo()` returns the default value.
172+
173+
Similar methods are generated for any of protocol buffers'
174+
[scalar types](https://developers.google.com/protocol-buffers/docs/proto#scalar).
175+
176+
### Singular Scalar Fields (proto3)
177+
For this field definition:
178+
179+
```protobuf
180+
int32 foo = 1;
181+
```
182+
183+
the compiler generates the following instance methods:
184+
185+
* `setFoo()`: Set the value of `foo`.
186+
* `getFoo()`: Get the value of `foo`.
187+
188+
189+
Similar methods are generated for any of protocol buffers'
190+
[scalar types](https://developers.google.com/protocol-buffers/docs/proto3).
191+
192+
193+
### Bytes Fields
194+
For this field definition:
195+
196+
```protobuf
197+
bytes foo = 1;
198+
```
199+
200+
the compiler generates the same methods as for other scalar value types. The
201+
`set..` method accepts either a base-64 encoded string or a `Uint8Array`. The
202+
`get..` method returns whichever representation was set last. However, there are
203+
also special methods generated that allow you to coerce the returned
204+
representation to your preferred version:
205+
206+
* `getFoo_asB64()`: Returns the value of `foo` as a base-64 encoded string.
207+
* `getFoo_asU8()`: Returns the value of `foo` as a `Uint8Array`.
208+
209+
### Singular Message Fields
210+
Given the message type:
211+
212+
```protobuf
213+
message Bar {}
214+
```
215+
216+
For a message with a `Bar` field:
217+
218+
```protobuf
219+
// proto2
220+
message Baz {
221+
optional Bar foo = 1;
222+
// The generated code is the same result if required instead of optional.
223+
}
224+
225+
// proto3
226+
message Baz {
227+
Bar foo = 1;
228+
}
229+
```
230+
231+
the compiler generates the following instance methods:
232+
233+
* `setFoo()`: Set the value of `foo`. When called with `undefined`, it is equivalent to calling `clearFoo()`.
234+
* `getFoo()`: Get the value of `foo`. Returns `undefined` if the field has not been set.
235+
* `hasFoo()`: Returns `true` if this field has been set. Equivalent to `!!getFoo()`.
236+
* `clearFoo()`: Clears the value of this field to `undefined`.
237+
238+
### Repeated Fields
239+
For this message with a repeated field:
240+
241+
```protobuf
242+
message Baz {
243+
repeated int32 foo = 1;
244+
}
245+
```
246+
247+
the compiler generates the following instance methods:
248+
249+
* `setFooList()`: Set the value of `foo` to the specified JavaScript array. Returns the message itself for chaining.
250+
* `addFoo()`: Appends a value of `foo` to the end of the list of foos that was in the message. Returns the outer message for chaining **only if** the added value was a primitive. For added messages, returns the message that was added.
251+
* `getFooList()`: Gets the value of `foo` as a JavaScript array. The returned array is never `undefined` and each element is never `undefined`. You should **no** mutate the list returned from this method.
252+
* `clearFooList()`: Clears the value of this field to `[]`.
253+
254+
255+
### Map Fields
256+
For this message with a map field:
257+
258+
```protobuf
259+
message Bar {}
260+
261+
message Baz {
262+
map<string, Bar> foo = 1;
263+
}
264+
```
265+
266+
the compiler generates the following instance method:
267+
268+
* `getFooMap()`: Returns the [Map](https://github.com/protocolbuffers/protobuf-javascript/blob/59a828fc713538404dcc9de8f42b4abfcfa5eb7d/map.js) containing `foo`'s key-value pairs. You can then use `Map` methods to interact with the map.
269+
270+
### Oneof Fields
271+
For this message with a oneof field:
272+
273+
```protobuf
274+
package account;
275+
276+
message Profile {
277+
oneof avatar {
278+
string image_url = 1;
279+
bytes image_data = 2;
280+
}
281+
}
282+
```
283+
284+
The class corresponding to `Profile` will have accessor methods just like regular fields (`getImageUrl()`, `getImageData()`). However, unlike regular fields, at most one of the fields in a oneof can be set at a time, so setting one field will clear the others. Also note that if you are using proto3, the compiler generates `has..` and `clear..` accessors for oneof fields, even for scalar types.
285+
286+
In addition to the regular accessor methods, the compiler generates a special method to check which field in the oneof is set: for our example, the method is `getAvatarCase()`. The possible return values for this are defined in the `AvatarCase` enum:
287+
288+
```js
289+
proto.account.Profile.AvatarCase = {
290+
AVATAR_NOT_SET: 0,
291+
IMAGE_URL: 1,
292+
IMAGE_DATA: 2
293+
};
294+
```
295+
296+
## Enumerations
297+
Given an enumeration like:
298+
299+
```protobuf
300+
message SearchRequest {
301+
enum Corpus {
302+
UNIVERSAL = 0;
303+
WEB = 1;
304+
IMAGES = 2;
305+
LOCAL = 3;
306+
NEWS = 4;
307+
PRODUCTS = 5;
308+
VIDEO = 6;
309+
}
310+
Corpus corpus = 1;
311+
...
312+
}
313+
```
314+
315+
the protocol buffer compiler generates a corresponding JavaScript enum.
316+
317+
```js
318+
proto.SearchRequest.Corpus = {
319+
UNIVERSAL: 0,
320+
WEB: 1,
321+
IMAGES: 2,
322+
LOCAL: 3,
323+
NEWS: 4,
324+
PRODUCTS: 5,
325+
VIDEO: 6
326+
};
327+
```
328+
329+
The compiler also generates getters and setters for enum fields, just like
330+
regular singular scalar fields. Note that in proto3, you can set an enum field
331+
to any value. In proto2, you should provide one of the specified enum values.
332+
333+
## Any
334+
Given an [`Any`](/protocol-buffers/docs/proto3#any) field like this:
335+
336+
```protobuf
337+
import "google/protobuf/any.proto";
338+
339+
package foo;
340+
341+
message Bar {}
342+
343+
message ErrorStatus {
344+
string message = 1;
345+
google.protobuf.Any details = 2;
346+
}
347+
```
348+
349+
In our generated code, the getter for the `details` field returns an instance of `proto.google.protobuf.Any`. This provides the following special methods:
350+
351+
```js
352+
/**
353+
* Returns the fully qualified proto name of the packed message, if any.
354+
* @return {string|undefined}
355+
*/
356+
proto.google.protobuf.Any.prototype.getTypeName;
357+
/**
358+
* Packs the given message instance into this Any.
359+
* @param {!Uint8Array} serialized The serialized data to pack.
360+
* @param {string} name The fully qualified proto name of the packed message.
361+
* @param {string=} opt_typeUrlPrefix the type URL prefix.
362+
*/
363+
proto.google.protobuf.Any.prototype.pack;
364+
/**
365+
* @template T
366+
* Unpacks this Any into the given message object.
367+
* @param {function(Uint8Array):T} deserialize Function that will deserialize
368+
* the binary data properly.
369+
* @param {string} name The expected type name of this message object.
370+
* @return {?T} If the name matched the expected name, returns the deserialized
371+
* object, otherwise returns null.
372+
*/
373+
proto.google.protobuf.Any.prototype.unpack;
374+
```
375+
376+
Example:
377+
378+
```js
379+
// Storing an arbitrary message type in Any.
380+
const status = new proto.foo.ErrorStatus();
381+
const any = new Any();
382+
const binarySerialized = ...;
383+
any.pack(binarySerialized, 'foo.Bar');
384+
console.log(any.getTypeName()); // foo.Bar
385+
// Reading an arbitrary message from Any.
386+
const bar = any.unpack(proto.foo.Bar.deserializeBinary, 'foo.Bar');
387+
```
388+

0 commit comments

Comments
 (0)