Skip to content

Commit c04d4a5

Browse files
committed
New: Implemented stubs for long.js / node buffers to be used where either one isn't wanted, see #718
1 parent a06691f commit c04d4a5

22 files changed

+423
-403
lines changed

README.md

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ Where bundle size is a factor, there is a suitable distribution for each of thes
7777
| light | 15.5kb | [dist/light][dist-light] | `require("protobufjs/light")` | All features except tokenizer, parser and bundled common types. Works with JSON definitions, pure reflection and static code.
7878
| minimal | 6.0kb+ | [dist/minimal][dist-minimal] | `require("protobufjs/minimal")` | Just enough to run static code. No reflection.
7979

80-
In case of doubt you can just use the full library.
80+
In case of doubt it is safe to just use the full library.
8181

8282
[dist-full]: https://github.com/dcodeIO/protobuf.js/tree/master/dist
8383
[dist-light]: https://github.com/dcodeIO/protobuf.js/tree/master/dist/light
@@ -88,7 +88,7 @@ Usage
8888

8989
Each message type provides a set of methods with each method doing just one thing. This allows to avoid unnecessary operations where [performance](#performance) is a concern but also forces a user to perform verification explicitly where necessary - for example when dealing with user input.
9090

91-
Note that **Message** refers to any message type below.
91+
Note that **Message** below refers to any message type. See the next section for the definition of a [valid message](#valid-message).
9292

9393
* **Message.verify**(message: `Object`): `null|string`<br />
9494
explicitly performs verification prior to encoding a plain object. Instead of throwing, it returns the error message as a string, if any.
@@ -160,29 +160,30 @@ Note that **Message** refers to any message type below.
160160

161161
See also: [ConversionOptions](http://dcode.io/protobuf.js/global.html#ConversionOptions)
162162

163-
**What is a valid message?**
163+
### Valid message
164164

165165
A valid message is an object not missing any required fields and exclusively using JS types for its fields that are understood by the wire format writer.
166166

167-
* Calling `Message.verify` with a valid message returns `null` and otherwise the error as a string.
168-
* Calling `Message.create` or `Message.encode` with any object assumes valid types.
167+
* Calling `Message.verify` with any object returns `null` if the object can be encoded as-is and otherwise the error as a string.
168+
* Calling `Message.create` or `Message.encode` must be called with a valid message.
169169
* Calling `Message.fromObject` with any object naively converts all values to the optimal JS type.
170170

171-
| Type | Expected JS type (create) | Naive conversion (fromObject)
172-
|--------|-----------------|-------------------
173-
| int32<br />uint32<br />sint32<br />fixed32<br />sfixed32 | `Number` (32 bit integer) | `value | 0`<br /> `value >>> 0`
174-
| int64<br />uint64<br />sint64<br />fixed64<br />sfixed64 | `Long`-like (optimal)<br />`Number` (53 bit integer) | `Long.fromValue(value)`<br />`parseInt(value, 10)` without long.js
171+
| Field type | Expected JS type (create, encode) | Naive conversion (fromObject)
172+
|------------|-----------------------------------|------------------------------
173+
| s-/u-/int32<br />s-/fixed32 | `Number` (32 bit integer) | `value | 0` if signed<br /> `value >>> 0` if unsigned
174+
| s-/u-/int64<br />s-/fixed64 | `Long`-like (optimal)<br />`Number` (53 bit integer) | `Long.fromValue(value)` with long.js<br />`parseInt(value, 10)` otherwise
175175
| float<br />double | `Number` | `Number(value)`
176176
| bool | `Boolean` | `Boolean(value)`
177177
| string | `String` | `String(value)`
178-
| bytes | `Uint8Array` (optimal)<br />`Buffer` (optimal)<br />`Array.<Number>` (8 bit integers)<br />`String` (base64) | `base64.decode(value)` if a String<br />`Object` with non-zero `.length` is kept
178+
| bytes | `Uint8Array` (optimal)<br />`Buffer` (optimal under node)<br />`Array.<Number>` (8 bit integers)<br />`String` (base64) | `base64.decode(value)` if a String<br />`Object` with non-zero `.length` is kept
179179
| enum | `Number` (32 bit integer) | Looks up the numeric id if a string
180180
| message | Valid message | `Message.fromObject(value)`
181181

182182
* Explicit `undefined` and `null` are considered as not set when optional.
183183
* Repeated fields are `Array.<T>`.
184-
* Map fields are `Object.<string,T>` with the key being the string representation of the respective value or an 8 characters long binary hash string for Long-likes.
184+
* Map fields are `Object.<string,T>` with the key being the string representation of the respective value or an 8 characters long binary hash string for `Long`-likes.
185185
* `String` refers to both objects and values while `Number` refers to values only.
186+
* Types marked as *optimal* provide the best performance because no conversion step (i.e. number to low and high bits or base64 string to buffer) is required.
186187

187188
Examples
188189
--------

cli/targets/static.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,9 @@ function buildType(ref, type) {
296296
jsType = "Object.<string," + jsType + ">";
297297
else if (field.repeated)
298298
jsType = "Array.<" + jsType + ">";
299-
typeDef.push("@property {" + jsType + "} " + (field.optional ? "[" + field.name + "]" : field.name) + " " + (field.comment || type.name + " " + field.name + "."));
299+
var name = util.safeProp(field.name);
300+
name = name.substring(1, name.charAt(0) === "[" ? name.length - 1 : name.length);
301+
typeDef.push("@property {" + jsType + "} " + (field.optional ? "[" + name + "]" : field.name) + " " + (field.comment || type.name + " " + field.name + "."));
300302
});
301303
push("");
302304
pushComment(typeDef);
@@ -391,7 +393,7 @@ function buildType(ref, type) {
391393
push("");
392394
pushComment([
393395
"Encodes the specified " + type.name + " message, length delimited. Does not implicitly {@link " + fullName + ".verify|verify} messages.",
394-
"@param {" + fullName + "|Object.<string,*>} message " + type.name + " message or plain object to encode",
396+
"@param {" + fullName + "$Properties} message " + type.name + " message or plain object to encode",
395397
"@param {$protobuf.Writer} [writer] Writer to encode to",
396398
"@returns {$protobuf.Writer} Writer"
397399
]);

debug.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
1+
// experimental - debug library entry point.
2+
13
"use strict";
2-
module.exports = require("./src/index-debug");
4+
module.exports = require("./src/index-debug");

index.d.ts

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1842,15 +1842,15 @@ export class Type extends NamespaceBase {
18421842
* @property {boolean} [objects=false] Sets empty objects for missing map fields even if `defaults=false`
18431843
* @property {boolean} [oneofs=false] Includes virtual oneof properties set to the present field's name, if any
18441844
*/
1845-
interface ConversionOptions {
1845+
type ConversionOptions = {
18461846
longs?: any;
18471847
enums?: any;
18481848
bytes?: any;
18491849
defaults?: boolean;
18501850
arrays?: boolean;
18511851
objects?: boolean;
18521852
oneofs?: boolean;
1853-
}
1853+
};
18541854

18551855
/**
18561856
* Common type constants.
@@ -2016,22 +2016,6 @@ export namespace types {
20162016
};
20172017
}
20182018

2019-
/**
2020-
* Any compatible Long instance.
2021-
*
2022-
* This is a minimal stand-alone definition of a Long instance. The actual type is that exported by long.js.
2023-
* @typedef Long
2024-
* @type {Object}
2025-
* @property {number} low Low bits
2026-
* @property {number} high High bits
2027-
* @property {boolean} unsigned Whether unsigned or not
2028-
*/
2029-
interface Long {
2030-
low: number;
2031-
high: number;
2032-
unsigned: boolean;
2033-
}
2034-
20352019
/**
20362020
* Various utility functions.
20372021
* @namespace
@@ -2870,10 +2854,10 @@ type FetchCallback = (error: Error, contents?: string) => void;
28702854
* @property {boolean} [binary=false] Whether expecting a binary response
28712855
* @property {boolean} [xhr=false] If `true`, forces the use of XMLHttpRequest
28722856
*/
2873-
interface FetchOptions {
2857+
type FetchOptions = {
28742858
binary?: boolean;
28752859
xhr?: boolean;
2876-
}
2860+
};
28772861

28782862
/**
28792863
* An allocator as used by {@link util.pool}.

index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
1+
// full library entry point.
2+
13
"use strict";
24
module.exports = require("./src/index");

lib/tsd-jsdoc/publish.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ function isClassLike(element) {
177177

178178
// tests if an element is considered to be an interface
179179
function isInterface(element) {
180-
return element && (element.kind === "interface" || getTypeOf(element) === "Object" && element.properties && element.properties.length);
180+
return element && element.kind === "interface";
181181
}
182182

183183
// tests if an element is considered to be a namespace
@@ -296,7 +296,13 @@ function writeFunctionSignature(element, isConstructor, isTypeDef) {
296296

297297
// writes (a typedef as) an interface
298298
function writeInterface(element) {
299-
writeln("interface ", element.name, " {");
299+
write("interface ", element.name);
300+
writeInterfaceBody(element);
301+
writeln();
302+
}
303+
304+
function writeInterfaceBody(element) {
305+
writeln("{");
300306
++indent;
301307
element.properties.forEach(function(property) {
302308
write(property.name);
@@ -305,7 +311,7 @@ function writeInterface(element) {
305311
writeln(": ", getTypeOf(property), ";");
306312
});
307313
--indent;
308-
writeln("}");
314+
write("}");
309315
}
310316

311317
//
@@ -524,7 +530,9 @@ function handleTypeDef(element, parent) {
524530
write("type ", element.name, " = ");
525531
if (element.type && element.type.names.length === 1 && element.type.names[0] === "function")
526532
writeFunctionSignature(element, false, true);
527-
else
533+
else if (getTypeOf(element) === "Object" && element.properties && element.properties.length) {
534+
writeInterfaceBody(element);
535+
} else
528536
write(getTypeOf(element));
529537
writeln(";");
530538
}

light.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
1+
// light library entry point.
2+
13
"use strict";
24
module.exports = require("./src/index-light");

minimal.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
1+
// minimal library entry point.
2+
13
"use strict";
2-
module.exports = require("./src/index-minimal");
4+
module.exports = require("./src/index-minimal");

runtime.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1-
// deprecated - compatibility layer for v6.5 and earlier
1+
// deprecated - compatibility layer for v6.5 and earlier (now named "minimal")
2+
23
"use strict";
3-
module.exports = require("./src/index-minimal");
4+
module.exports = require("./src/index-minimal");

src/util/longbits.js

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,6 @@ module.exports = LongBits;
33

44
var util = require("../util/minimal");
55

6-
/**
7-
* Any compatible Long instance.
8-
*
9-
* This is a minimal stand-alone definition of a Long instance. The actual type is that exported by long.js.
10-
* @typedef Long
11-
* @type {Object}
12-
* @property {number} low Low bits
13-
* @property {number} high High bits
14-
* @property {boolean} unsigned Whether unsigned or not
15-
*/
16-
176
/**
187
* Constructs new long bits.
198
* @classdesc Helper class for working with the low and high bits of a 64 bit value.

0 commit comments

Comments
 (0)