protobufjs
Advanced tools
Comparing version 6.5.3 to 6.6.0
@@ -93,3 +93,3 @@ { | ||
"init-declarations": 0, // because no-undef-init is on and we actually want undefineds | ||
"no-catch-shadow": 1, | ||
"no-catch-shadow": 0, // no IE8 support anyway | ||
"no-label-var": 1, | ||
@@ -96,0 +96,0 @@ "no-restricted-globals": 1, |
@@ -8,3 +8,3 @@ "use strict"; | ||
var commands = ["encode", "decode", "encode-browser", "decode-browser"]; | ||
var commands = ["encode", "decode", "encode-browser", "decode-browser", "fromjson"]; | ||
if (commands.indexOf(process.argv[2]) < 0) { // 0: node, 1: prof.js | ||
@@ -48,6 +48,21 @@ process.stderr.write("usage: " + path.basename(process.argv[1]) + " <" + commands.join("|") + "> [iterations=10000000]\n"); | ||
var root, Test, data, count; | ||
var root, json; | ||
if (process.argv[2] === "fromjson") { | ||
json = require("../tests/data/test.json"); | ||
if (process.argv.indexOf("--resolve") < 0) | ||
for (var k = 0; k < 10000; ++k) | ||
protobuf.Root.fromJSON(json); | ||
else | ||
for (var l = 0; l < 10000; ++l) | ||
protobuf.Root.fromJSON(json).resolveAll(); | ||
return; | ||
} | ||
var Test, data, count; | ||
if (process.argv.indexOf("--alt") < 0) { | ||
root = protobuf.parse(fs.readFileSync(require.resolve("../bench/bench.proto")).toString("utf8")).root; | ||
Test = root.lookup("Test"); | ||
json = JSON.stringify(root); | ||
data = require("../bench/bench.json"); | ||
@@ -54,0 +69,0 @@ count = 10000000; |
@@ -0,1 +1,41 @@ | ||
# [6.6.0](https://github.com/dcodeIO/protobuf.js/releases/tag/6.6.0) | ||
## Breaking | ||
[:hash:](https://github.com/dcodeIO/protobuf.js/commit/cdfe6bfba27fa1a1d0e61887597ad4bb16d7e5ed) Inlined / refactored away .testJSON, see [#653](https://github.com/dcodeIO/protobuf.js/issues/653)<br /> | ||
[:hash:](https://github.com/dcodeIO/protobuf.js/commit/6a483a529ef9345ed217a23394a136db0d9f7771) Refactored util.extend away<br /> | ||
[:hash:](https://github.com/dcodeIO/protobuf.js/commit/27b16351f3286468e539c2ab382de4b52667cf5e) Reflected and statically generated services use common utility, now work exactly the same<br /> | ||
[:hash:](https://github.com/dcodeIO/protobuf.js/commit/dca26badfb843a597f81e98738e2fda3f66c7341) fromObject now throws for entirely bogus values (repeated, map and inner message fields), fixes [#601](https://github.com/dcodeIO/protobuf.js/issues/601)<br /> | ||
[:hash:](https://github.com/dcodeIO/protobuf.js/commit/4bff9c356ef5c10b4aa34d1921a3b513e03dbb3d) Cleaned up library distributions, now is full / light / minimal with proper browserify support for each<br /> | ||
## Fixed | ||
[:hash:](https://github.com/dcodeIO/protobuf.js/commit/301f7762ef724229cd1df51e496eed8cfd2f10eb) Do not randomly remove slashes from comments, fixes [#656](https://github.com/dcodeIO/protobuf.js/issues/656)<br /> | ||
[:hash:](https://github.com/dcodeIO/protobuf.js/commit/ef7be352baaec26bdcdce01a71fbee47bbdeec15) Properly parse nested textformat options, also tackles [#655](https://github.com/dcodeIO/protobuf.js/issues/655)<br /> | ||
## New | ||
[:hash:](https://github.com/dcodeIO/protobuf.js/commit/b4f4f48f1949876ae92808b0a5ca5f2b29cc011c) Relieved the requirement to call .resolveAll() on roots in order to populate static code-compatible properties, see [#653](https://github.com/dcodeIO/protobuf.js/issues/653)<br /> | ||
[:hash:](https://github.com/dcodeIO/protobuf.js/commit/56c8ec4196d461383c3e1f271da02553d877ae81) Added a (highly experimental) debug build as a starting point for [#653](https://github.com/dcodeIO/protobuf.js/issues/653)<br /> | ||
[:hash:](https://github.com/dcodeIO/protobuf.js/commit/c5d291f9bab045385c5938ba0f6cdf50a315461f) Full build depends on light build depends on minimal build, shares all relevant code<br /> | ||
## CLI | ||
[:hash:](https://github.com/dcodeIO/protobuf.js/commit/735da4315a98a6960f3b5089115e308548b91c07) Also reuse specified root in pbjs for JSON modules, see [#653](https://github.com/dcodeIO/protobuf.js/issues/653)<br /> | ||
[:hash:](https://github.com/dcodeIO/protobuf.js/commit/3a056244d3acf339722d56549469a8df018e682e) Reuse specified root name in pbjs to be able to split definitions over multiple files more easily, see [#653](https://github.com/dcodeIO/protobuf.js/issues/653)<br /> | ||
## Docs | ||
[:hash:](https://github.com/dcodeIO/protobuf.js/commit/28ddf756ab83cc890761ef2bd84a0788d2ad040d) Improved pbjs/pbts examples, better covers reflection with definitions for static modules<br /> | ||
[:hash:](https://github.com/dcodeIO/protobuf.js/commit/6f0b44aea6cf72d23042810f05a7cede85239eb3) Fixed centered formatting on npm<br /> | ||
## Other | ||
[:hash:](https://github.com/dcodeIO/protobuf.js/commit/dd96dcdacb8eae94942f7016b8dc37a2569fe420) Various other minor improvements / assertions refactored away, see [#653](https://github.com/dcodeIO/protobuf.js/issues/653)<br /> | ||
[:hash:](https://github.com/dcodeIO/protobuf.js/commit/3317a76fb56b9b31bb07ad672d6bdda94b79b6c3) Fixed some common reflection deopt sites, see [#653](https://github.com/dcodeIO/protobuf.js/issues/653)<br /> | ||
[:hash:](https://github.com/dcodeIO/protobuf.js/commit/6a483a529ef9345ed217a23394a136db0d9f7771) Reflection performance pass, see [#653](https://github.com/dcodeIO/protobuf.js/issues/653)<br /> | ||
[:hash:](https://github.com/dcodeIO/protobuf.js/commit/6a483a529ef9345ed217a23394a136db0d9f7771) Added TS definitions to alternative builds' index files<br /> | ||
[:hash:](https://github.com/dcodeIO/protobuf.js/commit/6a483a529ef9345ed217a23394a136db0d9f7771) Removed unnecessary prototype aliases, improves gzip ratio<br /> | ||
[:hash:](https://github.com/dcodeIO/protobuf.js/commit/641625fd64aca55b1163845e6787b58054ac36ec) Unified behaviour of and docs on Class constructor / Class.create<br /> | ||
[:hash:](https://github.com/dcodeIO/protobuf.js/commit/7299929b37267af2100237d4f8b4ed8610b9f7e1) Statically generated services actually inherit from rpc.Service<br /> | ||
[:hash:](https://github.com/dcodeIO/protobuf.js/commit/f4cf75e4e4192910b52dd5864a32ee138bd4e508) Do not try to run sauce tests for PRs<br /> | ||
[:hash:](https://github.com/dcodeIO/protobuf.js/commit/33da148e2b750ce06591c1c66ce4c46ccecc3c8f) Added utility to enable/disable debugging extensions to experimental debug build<br /> | ||
[:hash:](https://github.com/dcodeIO/protobuf.js/commit/fdb1a729ae5f8ab762c51699bc4bb721102ef0c8) Fixed node 0.12 tests<br /> | ||
[:hash:](https://github.com/dcodeIO/protobuf.js/commit/6bc5bb4a7649d6b91a5944a9ae20178d004c8856) Fixed coverage<br /> | ||
[:hash:](https://github.com/dcodeIO/protobuf.js/commit/6f0b44aea6cf72d23042810f05a7cede85239eb3) Added a test case for [#652](https://github.com/dcodeIO/protobuf.js/issues/652)<br /> | ||
# [6.5.3](https://github.com/dcodeIO/protobuf.js/releases/tag/6.5.3) | ||
@@ -2,0 +42,0 @@ |
@@ -6,8 +6,17 @@ "use strict"; | ||
json_module.description = "JSON representation as a module" | ||
json_module.description = "JSON representation as a module"; | ||
function json_module(root, options, callback) { | ||
try { | ||
var output = "var $root = protobuf.Root.fromJSON(" + JSON.stringify(root, null, 2).replace(/^(?!$)/mg, " ").trim() + ").resolveAll();"; | ||
output = util.wrap(output, options); | ||
try { | ||
var rootProp = util.safeProp(options.root || "default"); | ||
var output = [ | ||
"var $root = ($protobuf.roots" + rootProp + " || ($protobuf.roots" + rootProp + " = new $protobuf.Root()))\n" | ||
]; | ||
if (root.options) { | ||
var optionsJson = util.jsonSafeProp(JSON.stringify(root.options, null, 2)); | ||
output.push(".setOptions(" + optionsJson + ")\n"); | ||
} | ||
var json = util.jsonSafeProp(JSON.stringify(root.nested, null, 2).trim()); | ||
output.push(".addJSON(" + json + ");"); | ||
output = util.wrap(output.join(""), options); | ||
process.nextTick(function() { | ||
@@ -14,0 +23,0 @@ callback(null, output); |
"use strict"; | ||
module.exports = json_target; | ||
var protobuf = require("../.."); | ||
json_target.description = "JSON representation" | ||
@@ -7,0 +5,0 @@ |
@@ -6,8 +6,6 @@ "use strict"; | ||
// - You can specify a custom wrapper with the --wrap argument. | ||
// - CommonJS modules depend on the minimal static runtime for reduced package size with browserify. | ||
// - CommonJS modules depend on the minimal build for reduced package size with browserify. | ||
// - AMD and global scope depend on the full library for now. | ||
var path = require("path"), | ||
fs = require("fs"), | ||
util = require("../util"); | ||
var util = require("../util"); | ||
@@ -23,3 +21,3 @@ var protobuf = require("../.."); | ||
try { | ||
output = util.wrap(output, protobuf.util.merge({ dependency: "protobufjs/runtime" }, options)); | ||
output = util.wrap(output, protobuf.util.merge({ dependency: "protobufjs/minimal" }, options)); | ||
} catch (e) { | ||
@@ -26,0 +24,0 @@ callback(e); |
@@ -20,3 +20,2 @@ "use strict"; | ||
var config = {}; | ||
var firstService = true; | ||
@@ -44,3 +43,4 @@ static_target.description = "Static code without reflection"; | ||
} | ||
push("var $root = {};"); | ||
var rootProp = cliUtil.safeProp(config.root || "default"); | ||
push("var $root = $protobuf.roots" + rootProp + " || ($protobuf.roots" + rootProp + " = {});"); | ||
buildNamespace(null, root); | ||
@@ -58,3 +58,2 @@ push(""); | ||
config = {}; | ||
firstService = true; | ||
} | ||
@@ -100,13 +99,2 @@ } | ||
// generate dot-notation property accessors where possible. this saves a few chars (i.e. m.hello | ||
// instead of m["hello"]) but has no measurable performance impact (on V8). not present within the | ||
// library itself because the reserved words check requires a rather longish regex. | ||
util.safeProp = (function(safeProp) { | ||
return function safeProp_dn(name) { | ||
return !/^[$\w]+$/.test(name) || cliUtil.reserved(name) | ||
? safeProp(name) | ||
: "." + name; | ||
} | ||
})(util.safeProp); | ||
function buildNamespace(ref, ns) { | ||
@@ -230,5 +218,4 @@ if (!ns) | ||
// enclose all but the first and last line in an iife returning our properly scoped function | ||
var lines = code.split(/\n/g); | ||
if (hasScope) | ||
if (hasScope) // enclose in an iife | ||
push(name(type.name) + "." + functionName + " = (function(" + Object.keys(scope).join(", ") + ") { return " + lines[0]); | ||
@@ -295,6 +282,5 @@ else | ||
++indent; | ||
push("if (properties) {"); | ||
push("if (properties)"); | ||
++indent; | ||
push("var keys = Object.keys(properties);"); | ||
push("for (var i = 0; i < keys.length; ++i)"); | ||
push("for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)"); | ||
++indent; | ||
@@ -304,3 +290,2 @@ push("this[keys[i]] = properties[keys[i]];"); | ||
--indent; | ||
push("}"); | ||
--indent; | ||
@@ -489,2 +474,3 @@ push("}"); | ||
"This is an alias of {@link " + fullName + ".fromObject}.", | ||
"@function", | ||
"@param {Object.<string,*>} object Plain object", | ||
@@ -532,27 +518,2 @@ "@returns {" + fullName + "} " + type.name | ||
if (firstService) { | ||
firstService = false; | ||
push(""); | ||
pushComment([ | ||
"RPC implementation passed to services performing a service request on network level, i.e. by utilizing http requests or websockets.", | ||
"@typedef RPCImpl", | ||
"@type {function}", | ||
"@param {$protobuf.Method} method Reflected method being called", | ||
"@param {Uint8Array} requestData Request data", | ||
"@param {RPCCallback} callback Callback function", | ||
"@returns {undefined}" | ||
]); | ||
push(""); | ||
pushComment([ | ||
"Node-style callback as used by {@link RPCImpl}.", | ||
"@typedef RPCCallback", | ||
"@type {function}", | ||
"@param {?Error} error Error, if any, otherwise `null`", | ||
"@param {Uint8Array} [responseData] Response data or `null` to signal end of stream, if there hasn't been an error", | ||
"@returns {undefined}" | ||
]); | ||
} | ||
push(""); | ||
@@ -563,31 +524,32 @@ pushComment([ | ||
"@exports " + fullName, | ||
"@extends $protobuf.rpc.Service", | ||
"@constructor", | ||
"@param {RPCImpl} rpc RPC implementation", | ||
"@param {$protobuf.RPCImpl} rpcImpl RPC implementation", | ||
"@param {boolean} [requestDelimited=false] Whether requests are length-delimited", | ||
"@param {boolean} [responseDelimited=false] Whether responses are length-delimited" | ||
]); | ||
push("function " + name(service.name) + "(rpc, requestDelimited, responseDelimited) {"); | ||
push("function " + name(service.name) + "(rpcImpl, requestDelimited, responseDelimited) {"); | ||
++indent; | ||
push(""); | ||
pushComment([ | ||
"RPC implementation.", | ||
"@type {RPCImpl}" | ||
]); | ||
push("this.rpc = rpc;"); | ||
push(""); | ||
pushComment([ | ||
"Whether requests are length-delimited.", | ||
"@type {boolean}" | ||
]); | ||
push("this.requestDelimited = Boolean(requestDelimited);"); | ||
push(""); | ||
pushComment([ | ||
"Whether responses are length-delimited.", | ||
"@type {boolean}" | ||
]); | ||
push("this.responseDelimited = Boolean(responseDelimited);"); | ||
push("$protobuf.rpc.Service.call(this, rpcImpl, requestDelimited, responseDelimited);"); | ||
--indent; | ||
push("}"); | ||
push(""); | ||
push("(" + name(service.name) + ".prototype = Object.create($protobuf.rpc.Service.prototype)).constructor = " + name(service.name) + ";"); | ||
if (config.create) { | ||
push(""); | ||
pushComment([ | ||
"Creates new " + service.name + " service using the specified rpc implementation.", | ||
"@param {$protobuf.RPCImpl} rpcImpl RPC implementation", | ||
"@param {boolean} [requestDelimited=false] Whether requests are length-delimited", | ||
"@param {boolean} [responseDelimited=false] Whether responses are length-delimited", | ||
"@returns {" + name(service.name) + "} RPC service. Useful where requests and/or responses are streamed." | ||
]); | ||
push(name(service.name) + ".create = function create(rpcImpl, requestDelimited, responseDelimited) {"); | ||
++indent; | ||
push("return new this(rpcImpl, requestDelimited, responseDelimited);"); | ||
--indent; | ||
push("};"); | ||
} | ||
service.methodsArray.forEach(function(method) { | ||
@@ -600,2 +562,3 @@ method.resolve(); | ||
"Callback as used by {@link " + name(service.name) + "#" + name(lcName) + "}.", | ||
// This is a more specialized version of protobuf.rpc.ServiceCallback | ||
"@typedef " + cbName, | ||
@@ -615,38 +578,15 @@ "@type {function}", | ||
++indent; | ||
push("var requestData;"); | ||
push("try {"); | ||
++indent; | ||
push("requestData = (this.requestDelimited ? $root" + name(method.resolvedRequestType.fullName) + ".encodeDelimited(request) : $root" + name(method.resolvedRequestType.fullName) + ".encode(request)).finish();"); | ||
--indent; | ||
push("} catch (err) {"); | ||
++indent; | ||
push("(typeof setImmediate === \"function\" ? setImmediate : setTimeout)(function() { callback(err); });"); | ||
push("return;"); | ||
--indent; | ||
push("}"); | ||
push("var self = this;"); | ||
push("this.rpc(" + name(lcName) + ", requestData, function(err, responseData) {"); | ||
++indent; | ||
push("if (err) {"); | ||
++indent; | ||
push("callback(err);"); | ||
push("return;"); | ||
--indent; | ||
push("}"); | ||
push("var response;"); | ||
push("try {"); | ||
++indent; | ||
push("response = self.responseDelimited ? $root" + name(method.resolvedResponseType.fullName) + ".decodeDelimited(responseData) : $root" + name(method.resolvedResponseType.fullName) + ".decode(responseData);"); | ||
--indent; | ||
push("} catch (err2) {"); | ||
++indent; | ||
push("callback(err2);"); | ||
push("return;"); | ||
--indent; | ||
push("}"); | ||
push("callback(null, response);"); | ||
--indent; | ||
push("});"); | ||
--indent; | ||
push("return this.rpcCall(" + name(lcName) + ", $root" + method.resolvedRequestType.fullName + ", $root" + method.resolvedResponseType.fullName + ", request, callback);"); | ||
--indent; | ||
push("};"); | ||
if (config.comments) | ||
push(""); | ||
pushComment([ | ||
method.comment || "Calls " + method.name + ".", | ||
"@name " + name(service.name) + "#" + lcName, | ||
"@function", | ||
"@param {" + method.resolvedRequestType.fullName.substring(1) + "|Object} request " + method.resolvedRequestType.name + " message or plain object", | ||
"@returns {Promise<"+method.resolvedResponseType.fullName.substring(1)+">} Promise", | ||
"@variation 2" | ||
]); | ||
}); | ||
@@ -653,0 +593,0 @@ } |
@@ -127,3 +127,2 @@ "use strict"; | ||
} | ||
wrap = wrap.replace(/%ROOT%/g, JSON.stringify(options.root || "default")); | ||
wrap = wrap.replace(/%DEPENDENCY%/g, JSON.stringify(options.dependency || "protobufjs")); | ||
@@ -144,4 +143,23 @@ wrap = wrap.replace(/( *)%OUTPUT%/, function($0, $1) { | ||
exports.reserved = function(name) { | ||
exports.reserved = function reserved(name) { | ||
return /^(?:do|if|in|for|let|new|try|var|case|else|enum|eval|false|null|this|true|void|with|break|catch|class|const|super|throw|while|yield|delete|export|import|public|return|static|switch|typeof|default|extends|finally|package|private|continue|debugger|function|arguments|interface|protected|implements|instanceof)$/.test(name); | ||
}; | ||
// generate dot-notation property accessors where possible. this saves a few chars (i.e. m.hello | ||
// instead of m["hello"]) but has no measurable performance impact (on V8). not present within the | ||
// library itself because the reserved words check requires a rather longish regex. | ||
exports.safeProp = protobuf.util.safeProp = (function(safeProp) { | ||
return function safeProp_dn(name) { | ||
return !/^[$\w]+$/.test(name) || exports.reserved(name) | ||
? safeProp(name) | ||
: "." + name; | ||
} | ||
})(protobuf.util.safeProp); | ||
exports.jsonSafeProp = function(json) { | ||
return json.replace(/^( +)"(\w+)":/mg, function($0, $1, $2) { | ||
return exports.safeProp($2).charAt(0) === "." | ||
? $1 + $2 + ":" | ||
: $0; | ||
}); | ||
}; |
@@ -6,3 +6,3 @@ define(["protobuf"], function($protobuf) { | ||
return $protobuf.roots[%ROOT%] = $root; | ||
return $root; | ||
}); |
@@ -7,2 +7,2 @@ "use strict"; | ||
module.exports = $protobuf.roots[%ROOT%] = $root; | ||
module.exports = $root; |
@@ -14,3 +14,3 @@ (function(global, factory) { /* global define, require, module */ | ||
return $protobuf.roots[%ROOT%] = $root; | ||
return $root; | ||
}); |
@@ -5,4 +5,2 @@ import * as $protobuf from "protobufjs"; | ||
$protobuf.roots[%ROOT%] = $root; | ||
export { $root as default }; |
@@ -1,5 +0,3 @@ | ||
This folder contains prebuilt browser versions of [protobuf.js](https://github.com/dcodeIO/protobuf.js). When sending pull requests, it is not required to update these. | ||
This folder contains prebuilt browser versions of the full library. When sending pull requests, it is not required to update these. | ||
Alternatively, you can also use [the minimal runtime](./runtime) when working with statically generated code or [the noparse build](./noparse) when working with JSON generated by `pbjs` *only*. | ||
Prebuilt files are in source control to enable pain-free frontend respectively CDN usage: | ||
@@ -6,0 +4,0 @@ |
@@ -1,74 +0,30 @@ | ||
var gulp = require("gulp"); | ||
var gulp = require("gulp"), | ||
bundle = require("./scripts/bundle"); | ||
var bundle = require("./scripts/bundle"); | ||
var defaultTask = []; | ||
gulp.task("default", [ | ||
"bundle-development", "bundle-production", "gzip-production", | ||
"bundle-development-runtime", "bundle-production-runtime", "gzip-production-runtime", | ||
"bundle-development-noparse", "bundle-production-noparse", "gzip-production-noparse" | ||
]); | ||
function defineTask(name, entry, target) { | ||
gulp.task(name + "-bundle", bundle.bind(this, { | ||
entry : entry, | ||
target : target | ||
})); | ||
gulp.task(name + "-minify" , bundle.bind(this, { | ||
entry : entry, | ||
target : target, | ||
compress : true | ||
})); | ||
gulp.task(name + "-compress", [ name + "-minify" ], function(callback) { | ||
bundle.compress( | ||
target + "/protobuf.min.js", | ||
target + "/protobuf.min.js.gz", | ||
callback | ||
); | ||
}); | ||
defaultTask.push(name + "-bundle", name + "-minify", name + "-compress"); | ||
} | ||
// Full build | ||
defineTask("full" , "./src/index" , "./dist" ); | ||
defineTask("light" , "./src/index-light" , "./dist/light" ); | ||
defineTask("minimal", "./src/index-minimal", "./dist/minimal"); | ||
gulp.task("bundle-development", bundle.bind(this, { | ||
entry : "./src", | ||
target : "./dist" | ||
})); | ||
gulp.task("bundle-production" , bundle.bind(this, { | ||
entry : "./src", | ||
target : "./dist", | ||
compress : true | ||
})); | ||
gulp.task("gzip-production", [ "bundle-production" ], function(callback) { | ||
bundle.compress( | ||
"./dist/protobuf.min.js", | ||
"./dist/protobuf.min.js.gz", | ||
callback | ||
); | ||
}); | ||
// Minimal runtime | ||
gulp.task("bundle-development-runtime", bundle.bind(this, { | ||
entry : "./runtime", | ||
target : "./dist/runtime" | ||
})); | ||
gulp.task("bundle-production-runtime" , bundle.bind(this, { | ||
entry : "./runtime", | ||
target : "./dist/runtime", | ||
compress : true | ||
})); | ||
gulp.task("gzip-production-runtime", [ "bundle-production-runtime" ], function(callback) { | ||
bundle.compress( | ||
"./dist/runtime/protobuf.min.js", | ||
"./dist/runtime/protobuf.min.js.gz", | ||
callback | ||
); | ||
}); | ||
// Noparse build | ||
gulp.task("bundle-development-noparse", bundle.bind(this, { | ||
entry : "./src", | ||
target : "./dist/noparse", | ||
exclude : [ "./tokenize", "./parse", "./common" ] | ||
})); | ||
gulp.task("bundle-production-noparse" , bundle.bind(this, { | ||
entry : "./src", | ||
target : "./dist/noparse", | ||
exclude : [ "./tokenize", "./parse", "./common" ], | ||
compress : true | ||
})); | ||
gulp.task("gzip-production-noparse", [ "bundle-production-noparse" ], function(callback) { | ||
bundle.compress( | ||
"./dist/noparse/protobuf.min.js", | ||
"./dist/noparse/protobuf.min.js.gz", | ||
callback | ||
); | ||
}); | ||
gulp.task("default", defaultTask); |
"use strict"; | ||
module.exports = require("./src"); | ||
module.exports = require("./src/index"); |
{ | ||
"name": "protobufjs", | ||
"version": "6.5.3", | ||
"version": "6.6.0", | ||
"versionScheme": "~", | ||
@@ -34,4 +34,4 @@ "description": "Protocol Buffers for JavaScript (& TypeScript).", | ||
"coverage-ci": "npm run coverage && cat coverage/lcov.info | coveralls", | ||
"docs": "jsdoc -c jsdoc.docs.json -R README.md", | ||
"lint": "eslint src runtime", | ||
"docs": "jsdoc -c jsdoc.docs.json -R README.md -P package.json --verbose --pedantic", | ||
"lint": "eslint src", | ||
"pages": "node scripts/pages", | ||
@@ -42,3 +42,3 @@ "prepublish": "node scripts/prepublish", | ||
"test": "tape -r ./lib/tape-adapter tests/*.js tests/node/*.js | tap-spec", | ||
"types": "node bin/pbts --main --global protobuf --out index.d.ts src && tsc tests/comp_typescript.ts --lib es2015 --noEmit --strictNullChecks && tsc tests/data/test.ts --lib es2015 --noEmit --strictNullChecks", | ||
"types": "node bin/pbts --main --global protobuf --out index.d.ts src && tsc tests/comp_typescript.ts --lib es2015 --noEmit --strictNullChecks && tsc tests/data/test.ts --lib es2015 --noEmit --strictNullChecks && tsc tests/data/rpc.ts --lib es2015 --noEmit --strictNullChecks", | ||
"zuul": "zuul --ui tape --no-coverage --concurrency 4 -- tests/*.js", | ||
@@ -54,3 +54,2 @@ "zuul-local": "zuul --ui tape --concurrency 1 --local 8080 --disable-tunnel -- tests/*.js", | ||
"@protobufjs/eventemitter": "^1.0.5", | ||
"@protobufjs/extend": "^1.0.2", | ||
"@protobufjs/fetch": "^1.0.4", | ||
@@ -75,3 +74,3 @@ "@protobufjs/inquire": "^1.0.2", | ||
"escodegen": "^1.8.1", | ||
"eslint": "^3.13.1", | ||
"eslint": "^3.14.0", | ||
"esprima": "^3.1.3", | ||
@@ -78,0 +77,0 @@ "estraverse": "^4.2.0", |
@@ -1,9 +0,3 @@ | ||
<h1 align="center"><img alt="protobuf.js" src="https://github.com/dcodeIO/protobuf.js/raw/master/pbjs.png" width="120" height="104" /></h1> | ||
<p align="center"> | ||
<a href="https://travis-ci.org/dcodeIO/protobuf.js"><img src="https://travis-ci.org/dcodeIO/protobuf.js.svg?branch=master" alt=""></a> | ||
<a href="https://coveralls.io/github/dcodeIO/protobuf.js"><img src="https://coveralls.io/repos/github/dcodeIO/protobuf.js/badge.svg?branch=master" alt=""></a> | ||
<a href="https://npmjs.org/package/protobufjs"><img src="https://img.shields.io/npm/v/protobufjs.svg" alt=""></a> | ||
<a href="https://npmjs.org/package/protobufjs"><img src="https://img.shields.io/npm/dm/protobufjs.svg" alt=""></a> | ||
<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=dcode%40dcode.io&item_name=Open%20Source%20Software%20Contribution&item_number=dcodeIO%2Fprotobuf.js"><img alt="donate ❤" src="https://img.shields.io/badge/donate-❤-ff2244.svg"></a> | ||
</p> | ||
<h1><p align="center"><img alt="protobuf.js" src="https://github.com/dcodeIO/protobuf.js/raw/master/pbjs.png" width="120" height="104" /></p></h1> | ||
<p align="center"><a href="https://travis-ci.org/dcodeIO/protobuf.js"><img src="https://travis-ci.org/dcodeIO/protobuf.js.svg?branch=master" alt=""></a> <a href="https://coveralls.io/github/dcodeIO/protobuf.js"><img src="https://coveralls.io/repos/github/dcodeIO/protobuf.js/badge.svg?branch=master" alt=""></a> <a href="https://npmjs.org/package/protobufjs"><img src="https://img.shields.io/npm/v/protobufjs.svg" alt=""></a> <a href="https://npmjs.org/package/protobufjs"><img src="https://img.shields.io/npm/dm/protobufjs.svg" alt=""></a> <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=dcode%40dcode.io&item_name=Open%20Source%20Software%20Donation&item_number=dcodeIO%2Fprotobuf.js"><img alt="donate ❤" src="https://img.shields.io/badge/donate-❤-ff2244.svg"></a></p> | ||
@@ -80,2 +74,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://developers.google.com/protocol-buffers/)). | ||
Additionally, the library is compiled in different versions. Which one to use depends on whether size is a factor and your use case: | ||
| Build | Downloads | How to require | Description | ||
|---------|------------------------------|---------------------------------|------------- | ||
| full | [dist][dist-full] | `require("protobufjs")` | All features. Works with everything. | ||
| light | [dist/light][dist-light] | `require("protobufjs/light")` | All features except tokenizer, parser and bundled common types. Works with reflection, JSON definitions and static code. | ||
| minimal | [dist/minimal][dist-minimal] | `require("protobufjs/minimal")` | Just enough to run statically generated code. Works with static code only. | ||
Examples | ||
@@ -166,3 +168,3 @@ -------- | ||
While only useful for the adventurous cherishing an aversion to [generated static code](https://github.com/dcodeIO/protobuf.js#command-line), it's also possible to use the Reader/Writer interface directly depending just on the [minimal runtime](https://github.com/dcodeIO/protobuf.js/tree/master/dist/runtime) ([basic example](https://github.com/dcodeIO/protobuf.js/blob/master/examples/reader-writer.js)). | ||
While only useful for the adventurous cherishing an aversion to [generated static code](https://github.com/dcodeIO/protobuf.js#command-line), it's also possible to use the Reader/Writer interface directly depending just on the [minimal library][dist-minimal] ([basic example](https://github.com/dcodeIO/protobuf.js/blob/master/examples/reader-writer.js)). | ||
@@ -307,2 +309,10 @@ Easy ways to obtain example code snippets are either setting `protobuf.util.codegen.verbose = true` while watching the magic as it happens, or simply inspecting generated static code. | ||
As you might have noticed, `pbjs` is also capable of generating static code. For example | ||
``` | ||
$> pbjs -t static-module -w commonjs -o compiled.js file1.proto file2.proto | ||
``` | ||
will generate static code for definitions within `file1.proto` and `file2.proto` to a CommonJS module `compiled.js`, which then can be used with just the [minimal library][dist-minimal]. | ||
**ProTip!** Documenting your .proto files with `/** ... */`-blocks or (trailing) `/// ...` lines translates to generated static code. | ||
@@ -330,2 +340,29 @@ | ||
Picking up on the example above, the following not just generates static code to a CommonJS module `compiled.js` but also its respective TypeScript definitions to `compiled.d.ts`: | ||
``` | ||
$> pbjs -t static-module -w commonjs -o compiled.js file1.proto file2.proto | ||
$> pbts -o compiled.d.ts compiled.js | ||
``` | ||
Additionally, TypeScript definitions of static modules are compatible with reflection, as long as the following conditions are met: | ||
1. Instead of using `new SomeMessage(...)`, always use `SomeMessage.create(...)` because reflection objects do not provide a constructor. | ||
2. Types, services and enums must start with an uppercase letter to become available as properties of the reflected types as well (i.e. to be able to use `MyMessage.MyEnum` instead of `root.lookup("MyMessage.MyEnum")`). | ||
For example, the following generates a `bundle.json` and a `bundle.d.ts`, but no static code: | ||
``` | ||
$> pbjs -t json-module -w commonjs -o bundle.json file1.proto file2.proto | ||
$> pbjs -t static-module file1.proto file2.proto | pbts -o bundle.d.ts - | ||
``` | ||
### On reflection vs. static code | ||
While using .proto files requires the [full library][dist-full] (about 18.5kb gzipped) or JSON at least the [light library][dist-light] (about 15.5kb gzipped), pretty much all code but the relatively short descriptors is shared and all features including reflection and the parser are available. | ||
Static code, on the other hand, requires just the [minimal library][dist-minimal] (about 5.5kb gzipped), but generates additional, albeit editable, source code without any reflection features. | ||
There is no significant difference performance-wise as the code generated statically is pretty much the same as generated at runtime and both are largely interchangeable as seen in the previous section. | ||
### Using pbjs and pbts programmatically | ||
@@ -345,16 +382,2 @@ | ||
### Descriptors vs. static modules | ||
While .proto and JSON files require the full library (about 18.5kb gzipped), pretty much all code but the relatively short descriptors is shared and all features including reflection and the parser are available. | ||
Static code, on the other hand, requires just the minimal runtime (about 5.5kb gzipped), but generates additional, albeit editable, source code without any reflection features. | ||
There is no difference performance-wise as the code generated statically is pretty much the same as generated at runtime. | ||
Additionally, JSON modules can be used with TypeScript definitions generated for their static counterparts as long as the following conditions are met: | ||
1. Use `SomeMessage.create(...)` instead of `new SomeMessage(...)` (reflection does not provide such a constructor). | ||
2. Types, services and enums must start with an uppercase letter to become available as properties of the reflected types as well. | ||
3. When using a TypeScript definition with custom code, `resolveAll()` must be called once on the root instance to populate these additional properties (JSON modules do this automatically). | ||
Performance | ||
@@ -453,3 +476,3 @@ ----------- | ||
Building the development and production versions with their respective source maps to `dist/`: | ||
Building the respective development and production versions with their respective source maps to `dist/`: | ||
@@ -480,1 +503,5 @@ ``` | ||
**License:** [BSD 3-Clause License](https://opensource.org/licenses/BSD-3-Clause) | ||
[dist-full]: https://github.com/dcodeIO/protobuf.js/tree/master/dist | ||
[dist-light]: https://github.com/dcodeIO/protobuf.js/tree/master/dist/light | ||
[dist-minimal]: https://github.com/dcodeIO/protobuf.js/tree/master/dist/minimal |
@@ -26,5 +26,10 @@ "use strict"; | ||
throw err; | ||
var pathToRuntime = path.relative(path.dirname(out), "runtime").replace(/\\/g, "/"); | ||
fs.writeFileSync(out, fs.readFileSync(out).toString("utf8").replace(/"protobufjs\/runtime"/g, JSON.stringify(pathToRuntime)), "utf8"); | ||
var pathToProtobufjs = path.relative(path.dirname(out), "minimal").replace(/\\/g, "/"); | ||
fs.writeFileSync(out, fs.readFileSync(out).toString("utf8").replace(/"protobufjs\/minimal"/g, JSON.stringify(pathToProtobufjs)), "utf8"); | ||
process.stdout.write("pbjs: " + file + " -> " + out + "\n"); | ||
try { | ||
require(path.join(__dirname, "..", out)); | ||
} catch (err2) { | ||
process.stderr.write("ERROR: " + err2.message + "\n"); | ||
} | ||
}) | ||
@@ -34,3 +39,4 @@ }); | ||
[ | ||
"tests/data/test.js" | ||
"tests/data/test.js", | ||
"tests/data/rpc.js" | ||
] | ||
@@ -37,0 +43,0 @@ .forEach(function(file) { |
@@ -10,14 +10,5 @@ "use strict"; | ||
/** | ||
* Constructs a class instance, which is also a {@link Message} prototype. | ||
* Constructs a new message prototype for the specified reflected type and sets up its constructor. | ||
* @classdesc Runtime class providing the tools to create your own custom classes. | ||
* @constructor | ||
* @param {Type} type Reflected type | ||
*/ | ||
function Class(type) { | ||
return create(type); | ||
} | ||
/** | ||
* Constructs a new message prototype for the specified reflected type and sets up its constructor. | ||
* @memberof Class | ||
* @param {Type} type Reflected message type | ||
@@ -27,3 +18,3 @@ * @param {*} [ctor] Custom constructor to set up, defaults to create a generic one if omitted | ||
*/ | ||
function create(type, ctor) { | ||
function Class(type, ctor) { | ||
if (!Type) | ||
@@ -40,4 +31,4 @@ Type = require("./type"); | ||
// create named constructor functions (codegen is required anyway) | ||
ctor = util.codegen("p")("return ctor.call(this,p)").eof(type.name, { | ||
ctor: Message | ||
ctor = util.codegen("p")("return c.call(this,p)").eof(type.name, { | ||
c: Message | ||
}); | ||
@@ -49,4 +40,3 @@ | ||
// new Class() -> Message.prototype | ||
var prototype = ctor.prototype = new Message(); | ||
prototype.constructor = ctor; | ||
(ctor.prototype = new Message()).constructor = ctor; | ||
@@ -58,23 +48,26 @@ // Static methods on Message are instance methods on Class and vice versa | ||
ctor.$type = type; | ||
prototype.$type = type; | ||
ctor.prototype.$type = type; | ||
// Messages have non-enumerable default values on their prototype | ||
type.fieldsArray.forEach(function(field) { | ||
var i = 0; | ||
for (; i < /* initializes */ type.fieldsArray.length; ++i) { | ||
// objects on the prototype must be immmutable. users must assign a new object instance and | ||
// cannot use Array#push on empty arrays on the prototype for example, as this would modify | ||
// the value on the prototype for ALL messages of this type. Hence, these objects are frozen. | ||
prototype[field.name] = Array.isArray(field.resolve().defaultValue) | ||
ctor.prototype[type._fieldsArray[i].name] = Array.isArray(type._fieldsArray[i].resolve().defaultValue) | ||
? util.emptyArray | ||
: util.isObject(field.defaultValue) && !field.long | ||
: util.isObject(type._fieldsArray[i].defaultValue) && !type._fieldsArray[i].long | ||
? util.emptyObject | ||
: field.defaultValue; | ||
}); | ||
: type._fieldsArray[i].defaultValue; // if a long, it is frozen when initialized | ||
} | ||
// Messages have non-enumerable getters and setters for each virtual oneof field | ||
type.oneofsArray.forEach(function(oneof) { | ||
Object.defineProperty(prototype, oneof.resolve().name, { | ||
get: util.oneOfGetter(oneof.oneof), | ||
set: util.oneOfSetter(oneof.oneof) | ||
}); | ||
}); | ||
var ctorProperties = {}; | ||
for (i = 0; i < /* initializes */ type.oneofsArray.length; ++i) | ||
ctorProperties[type._oneofsArray[i].resolve().name] = { | ||
get: util.oneOfGetter(type._oneofsArray[i].oneof), | ||
set: util.oneOfSetter(type._oneofsArray[i].oneof) | ||
}; | ||
if (i) | ||
Object.defineProperties(ctor.prototype, ctorProperties); | ||
@@ -84,6 +77,13 @@ // Register | ||
return prototype; | ||
return ctor.prototype; | ||
} | ||
Class.create = create; | ||
/** | ||
* Constructs a new message prototype for the specified reflected type and sets up its constructor. | ||
* @function | ||
* @param {Type} type Reflected message type | ||
* @param {*} [ctor] Custom constructor to set up, defaults to create a generic one if omitted | ||
* @returns {Message} Message prototype | ||
*/ | ||
Class.create = Class; | ||
@@ -90,0 +90,0 @@ // Static methods on Message are instance methods on Class and vice versa |
@@ -16,2 +16,8 @@ "use strict"; | ||
* @property {Object.<string,*>} google/protobuf/wrappers.proto Wrappers | ||
* @example | ||
* // manually provides descriptor.proto (assumes google/protobuf/ namespace and .proto extension) | ||
* protobuf.common("descriptor", descriptorJson); | ||
* | ||
* // manually provides a custom definition (uses my.foo namespace) | ||
* protobuf.common("my/foo/bar.proto", myFooBarJson); | ||
*/ | ||
@@ -18,0 +24,0 @@ function common(name, json) { |
@@ -23,16 +23,17 @@ "use strict"; | ||
if (field.resolvedType) { | ||
if (field.resolvedType instanceof Enum) { | ||
var values = field.resolvedType.values; gen | ||
if (field.resolvedType instanceof Enum) { gen | ||
("switch(d%s){", prop); | ||
Object.keys(values).forEach(function(key) { | ||
if (field.repeated && values[key] === field.typeDefault) gen | ||
for (var values = field.resolvedType.values, keys = Object.keys(values), i = 0; i < keys.length; ++i) { | ||
if (field.repeated && values[keys[i]] === field.typeDefault) gen | ||
("default:"); | ||
gen | ||
("case%j:", key) | ||
("case %j:", values[key]) | ||
("m%s=%j", prop, values[key]) | ||
("case%j:", keys[i]) | ||
("case %j:", values[keys[i]]) | ||
("m%s=%j", prop, values[keys[i]]) | ||
("break"); | ||
}); gen | ||
} gen | ||
("}"); | ||
} else gen | ||
("if(typeof d%s!==\"object\")", prop) | ||
("throw TypeError(%j)", field.fullName + ": object expected") | ||
("m%s=types[%d].fromObject(d%s)", prop, fieldIndex, prop); | ||
@@ -74,3 +75,3 @@ } else { | ||
("util.base64.decode(d%s,m%s=util.newBuffer(util.base64.length(d%s)),0)", prop, prop, prop) | ||
("else if(d%s&&d%s.length)", prop, prop) | ||
("else if(d%s.length)", prop) | ||
("m%s=d%s", prop, prop); | ||
@@ -115,2 +116,4 @@ break; | ||
("if(d%s){", prop) | ||
("if(typeof d%s!==\"object\")", prop) | ||
("throw TypeError(%j)", field.fullName + ": object expected") | ||
("m%s={}", prop) | ||
@@ -125,2 +128,4 @@ ("for(var ks=Object.keys(d%s),i=0;i<ks.length;++i){", prop); | ||
("if(d%s){", prop) | ||
("if(!Array.isArray(d%s))", prop) | ||
("throw TypeError(%j)", field.fullName + ": array expected") | ||
("m%s=[]", prop) | ||
@@ -202,23 +207,36 @@ ("for(var i=0;i<d%s.length;++i){", prop); | ||
("var d={}"); | ||
var repeatedFields = fields.filter(function(field) { return field.resolve().repeated; }); | ||
var repeatedFields = [], | ||
mapFields = [], | ||
otherFields = [], | ||
i = 0; | ||
for (; i < fields.length; ++i) | ||
if (fields[i].resolve().repeated) | ||
repeatedFields.push(fields[i]); | ||
else if (fields[i].map) | ||
mapFields.push(fields[i]); | ||
else | ||
otherFields.push(fields[i]); | ||
if (repeatedFields.length) { gen | ||
("if(o.arrays||o.defaults){"); | ||
repeatedFields.forEach(function(field) { gen | ||
("d%s=[]", util.safeProp(field.name)); | ||
}); gen | ||
for (i = 0; i < repeatedFields.length; ++i) gen | ||
("d%s=[]", util.safeProp(repeatedFields[i].name)); | ||
gen | ||
("}"); | ||
} | ||
var mapFields = fields.filter(function(field) { return field.map; }); | ||
if (mapFields.length) { gen | ||
("if(o.objects||o.defaults){"); | ||
mapFields.forEach(function(field) { gen | ||
("d%s={}", util.safeProp(field.name)); | ||
}); gen | ||
for (i = 0; i < mapFields.length; ++i) gen | ||
("d%s={}", util.safeProp(mapFields[i].name)); | ||
gen | ||
("}"); | ||
} | ||
var otherFields = fields.filter(function(field) { return !(field.repeated || field.map); }); | ||
if (otherFields.length) { gen | ||
("if(o.defaults){"); | ||
otherFields.forEach(function(field) { | ||
var prop = util.safeProp(field.name); | ||
for (i = 0, field; i < otherFields.length; ++i) { | ||
var field = otherFields[i], | ||
prop = util.safeProp(field.name); | ||
if (field.resolvedType instanceof Enum) gen | ||
@@ -236,6 +254,6 @@ ("d%s=o.enums===String?%j:%j", prop, field.resolvedType.valuesById[field.typeDefault], field.typeDefault); | ||
("d%s=%j", prop, field.typeDefault); // also messages (=null) | ||
}); gen | ||
} gen | ||
("}"); | ||
} | ||
for (var i = 0; i < fields.length; ++i) { | ||
for (i = 0, field; i < fields.length; ++i) { | ||
var field = fields[i], | ||
@@ -242,0 +260,0 @@ prop = util.safeProp(field.name); gen |
@@ -18,3 +18,2 @@ "use strict"; | ||
/* eslint-disable no-unexpected-multiline */ | ||
var fields = mtype.fieldsArray; | ||
var gen = util.codegen("r", "l") | ||
@@ -32,4 +31,4 @@ ("if(!(r instanceof Reader))") | ||
for (var i = 0; i < fields.length; ++i) { | ||
var field = fields[i].resolve(), | ||
for (var i = 0; i < /* initializes */ mtype.fieldsArray.length; ++i) { | ||
var field = mtype._fieldsArray[i].resolve(), | ||
type = field.resolvedType instanceof Enum ? "uint32" : field.type, | ||
@@ -36,0 +35,0 @@ ref = "m" + util.safeProp(field.name); gen |
@@ -30,4 +30,2 @@ "use strict"; | ||
/* eslint-disable no-unexpected-multiline, block-scoped-var, no-redeclare */ | ||
var fields = mtype.fieldsArray; | ||
var oneofs = mtype.oneofsArray; | ||
var gen = util.codegen("m", "w") | ||
@@ -38,4 +36,4 @@ ("if(!w)") | ||
var i, ref; | ||
for (var i = 0; i < fields.length; ++i) { | ||
var field = fields[i].resolve(); | ||
for (var i = 0; i < /* initializes */ mtype.fieldsArray.length; ++i) { | ||
var field = mtype._fieldsArray[i].resolve(); | ||
if (field.partOf) // see below for oneofs | ||
@@ -110,8 +108,7 @@ continue; | ||
// oneofs | ||
for (var i = 0; i < oneofs.length; ++i) { | ||
var oneof = oneofs[i]; gen | ||
for (var i = 0; i < /* initializes */ mtype.oneofsArray.length; ++i) { | ||
var oneof = mtype._oneofsArray[i]; gen | ||
("switch(%s){", "m" + util.safeProp(oneof.name)); | ||
var oneofFields = oneof.fieldsArray; | ||
for (var j = 0; j < oneofFields.length; ++j) { | ||
var field = oneofFields[j], | ||
for (var j = 0; j < /* direct */ oneof.fieldsArray.length; ++j) { | ||
var field = oneof.fieldsArray[j], | ||
type = field.resolvedType instanceof Enum ? "uint32" : field.type, | ||
@@ -122,3 +119,3 @@ wireType = types.basic[type]; | ||
if (wireType === undefined) | ||
genTypePartial(gen, field, fields.indexOf(field), ref); | ||
genTypePartial(gen, field, mtype._fieldsArray.indexOf(field), ref); | ||
else gen | ||
@@ -125,0 +122,0 @@ ("w.uint32(%d).%s(%s)", (field.id << 3 | wireType) >>> 0, type, ref); |
@@ -6,7 +6,4 @@ "use strict"; | ||
var ReflectionObject = require("./object"); | ||
/** @alias Enum.prototype */ | ||
var EnumPrototype = ReflectionObject.extend(Enum); | ||
((Enum.prototype = Object.create(ReflectionObject.prototype)).constructor = Enum).className = "Enum"; | ||
Enum.className = "Enum"; | ||
var util = require("./util"); | ||
@@ -26,2 +23,5 @@ | ||
if (values && typeof values !== "object") | ||
throw TypeError("values must be an object"); | ||
/** | ||
@@ -49,18 +49,8 @@ * Enum values by id. | ||
var self = this; | ||
Object.keys(values || {}).forEach(function(key) { | ||
self.valuesById[self.values[key] = values[key]] = key; | ||
}); | ||
if (values) | ||
for (var keys = Object.keys(values), i = 0; i < keys.length; ++i) | ||
this.valuesById[ this.values[keys[i]] = values[keys[i]] ] = keys[i]; | ||
} | ||
/** | ||
* Tests if the specified JSON object describes an enum. | ||
* @param {*} json JSON object to test | ||
* @returns {boolean} `true` if the object describes an enum | ||
*/ | ||
Enum.testJSON = function testJSON(json) { | ||
return Boolean(json && json.values); | ||
}; | ||
/** | ||
* Creates an enum from JSON. | ||
@@ -79,3 +69,3 @@ * @param {string} name Enum name | ||
*/ | ||
EnumPrototype.toJSON = function toJSON() { | ||
Enum.prototype.toJSON = function toJSON() { | ||
return { | ||
@@ -96,19 +86,20 @@ options : this.options, | ||
*/ | ||
EnumPrototype.add = function(name, id, comment) { | ||
Enum.prototype.add = function(name, id, comment) { | ||
// utilized by the parser but not by .fromJSON | ||
/* istanbul ignore next */ | ||
if (!util.isString(name)) | ||
throw TypeError("name must be a string"); | ||
/* istanbul ignore next */ | ||
if (!util.isInteger(id)) | ||
throw TypeError("id must be an integer"); | ||
/* istanbul ignore next */ | ||
if (this.values[name] !== undefined) | ||
throw Error("duplicate name '" + name + "' in " + this); | ||
/* istanbul ignore next */ | ||
throw Error("duplicate name"); | ||
if (this.valuesById[id] !== undefined) | ||
throw Error("duplicate id " + id + " in " + this); | ||
throw Error("duplicate id"); | ||
this.valuesById[this.values[name] = id] = name; | ||
this.comments[name] = comment || null; | ||
return this; | ||
@@ -124,14 +115,16 @@ }; | ||
*/ | ||
EnumPrototype.remove = function(name) { | ||
/* istanbul ignore next */ | ||
Enum.prototype.remove = function(name) { | ||
if (!util.isString(name)) | ||
throw TypeError("name must be a string"); | ||
var val = this.values[name]; | ||
/* istanbul ignore next */ | ||
if (val === undefined) | ||
throw Error("'" + name + "' is not a name of " + this); | ||
throw Error("name does not exist"); | ||
delete this.valuesById[val]; | ||
delete this.values[name]; | ||
delete this.comments[name]; | ||
return this; | ||
}; |
@@ -6,14 +6,10 @@ "use strict"; | ||
var ReflectionObject = require("./object"); | ||
/** @alias Field.prototype */ | ||
var FieldPrototype = ReflectionObject.extend(Field); | ||
((Field.prototype = Object.create(ReflectionObject.prototype)).constructor = Field).className = "Field"; | ||
Field.className = "Field"; | ||
var Enum = require("./enum"), | ||
types = require("./types"), | ||
util = require("./util"); | ||
var Enum = require("./enum"), | ||
types = require("./types"), | ||
util = require("./util"); | ||
var Type; // cyclic | ||
var Type, // cyclic | ||
MapField; // cyclic | ||
/** | ||
@@ -32,2 +28,3 @@ * Constructs a new message field instance. Note that {@link MapField|map fields} have their own class. | ||
function Field(name, id, type, rule, extend, options) { | ||
if (util.isObject(rule)) { | ||
@@ -40,17 +37,17 @@ options = rule; | ||
} | ||
ReflectionObject.call(this, name, options); | ||
/* istanbul ignore next */ | ||
if (!util.isInteger(id) || id < 0) | ||
throw TypeError("id must be a non-negative integer"); | ||
/* istanbul ignore next */ | ||
if (!util.isString(type)) | ||
throw TypeError("type must be a string"); | ||
/* istanbul ignore next */ | ||
if (extend !== undefined && !util.isString(extend)) | ||
throw TypeError("extend must be a string"); | ||
/* istanbul ignore next */ | ||
if (rule !== undefined && !/^required|optional|repeated$/.test(rule = rule.toString().toLowerCase())) | ||
throw TypeError("rule must be a string rule"); | ||
if (extend !== undefined && !util.isString(extend)) | ||
throw TypeError("extend must be a string"); | ||
/** | ||
@@ -172,3 +169,3 @@ * Field rule, if any. | ||
*/ | ||
Object.defineProperty(FieldPrototype, "packed", { | ||
Object.defineProperty(Field.prototype, "packed", { | ||
get: function() { | ||
@@ -185,4 +182,4 @@ // defaults to packed=true if not explicity set to false | ||
*/ | ||
FieldPrototype.setOption = function setOption(name, value, ifNotSet) { | ||
if (name === "packed") | ||
Field.prototype.setOption = function setOption(name, value, ifNotSet) { | ||
if (name === "packed") // clear cached before setting | ||
this._packed = null; | ||
@@ -193,11 +190,2 @@ return ReflectionObject.prototype.setOption.call(this, name, value, ifNotSet); | ||
/** | ||
* Tests if the specified JSON object describes a field. | ||
* @param {*} json Any JSON object to test | ||
* @returns {boolean} `true` if the object describes a field | ||
*/ | ||
Field.testJSON = function testJSON(json) { | ||
return Boolean(json && json.id !== undefined); | ||
}; | ||
/** | ||
* Constructs a field from JSON. | ||
@@ -210,7 +198,2 @@ * @param {string} name Field name | ||
Field.fromJSON = function fromJSON(name, json) { | ||
if (json.keyType !== undefined) { | ||
if (!MapField) | ||
MapField = require("./mapfield"); | ||
return MapField.fromJSON(name, json); | ||
} | ||
return new Field(name, json.id, json.type, json.rule, json.extend, json.options); | ||
@@ -222,3 +205,3 @@ }; | ||
*/ | ||
FieldPrototype.toJSON = function toJSON() { | ||
Field.prototype.toJSON = function toJSON() { | ||
return { | ||
@@ -238,13 +221,16 @@ rule : this.rule !== "optional" && this.rule || undefined, | ||
*/ | ||
FieldPrototype.resolve = function resolve() { | ||
Field.prototype.resolve = function resolve() { | ||
if (this.resolved) | ||
return this; | ||
if ((this.typeDefault = types.defaults[this.type]) === undefined) { | ||
// if not a basic type, resolve it | ||
if ((this.typeDefault = types.defaults[this.type]) === undefined) { // if not a basic type, resolve it | ||
/* istanbul ignore if */ | ||
if (!Type) | ||
Type = require("./type"); | ||
if (this.resolvedType = this.parent.lookup(this.type, Type)) | ||
this.typeDefault = null; | ||
else /* istanbul ignore else */ if (this.resolvedType = this.parent.lookup(this.type, Enum)) | ||
else if (this.resolvedType = this.parent.lookup(this.type, Enum)) | ||
this.typeDefault = this.resolvedType.values[Object.keys(this.resolvedType.values)[0]]; // first defined | ||
@@ -265,5 +251,7 @@ else | ||
this.typeDefault = util.Long.fromNumber(this.typeDefault, this.type.charAt(0) === "u"); | ||
/* istanbul ignore else */ | ||
if (Object.freeze) | ||
Object.freeze(this.typeDefault); // long instances are meant to be immutable anyway (i.e. use small int cache that even requires it) | ||
} else if (this.bytes && typeof this.typeDefault === "string") { | ||
@@ -278,7 +266,7 @@ var buf; | ||
// account for maps and repeated fields | ||
// take special care of maps and repeated fields | ||
if (this.map) | ||
this.defaultValue = {}; | ||
this.defaultValue = util.emptyObject; | ||
else if (this.repeated) | ||
this.defaultValue = []; | ||
this.defaultValue = util.emptyArray; | ||
else | ||
@@ -285,0 +273,0 @@ this.defaultValue = this.typeDefault; |
143
src/index.js
"use strict"; | ||
var protobuf = global.protobuf = exports; | ||
var protobuf = module.exports = require("./index-light"); | ||
/** | ||
* A node-style callback as used by {@link load} and {@link Root#load}. | ||
* @typedef LoadCallback | ||
* @type {function} | ||
* @param {?Error} error Error, if any, otherwise `null` | ||
* @param {Root} [root] Root, if there hasn't been an error | ||
* @returns {undefined} | ||
*/ | ||
protobuf.build = "full"; | ||
/** | ||
* Loads one or multiple .proto or preprocessed .json files into a common root namespace and calls the callback. | ||
* @param {string|string[]} filename One or multiple files to load | ||
* @param {Root} root Root namespace, defaults to create a new one if omitted. | ||
* @param {LoadCallback} callback Callback function | ||
* @returns {undefined} | ||
* @see {@link Root#load} | ||
*/ | ||
function load(filename, root, callback) { | ||
if (typeof root === "function") { | ||
callback = root; | ||
root = new protobuf.Root(); | ||
} else if (!root) | ||
root = new protobuf.Root(); | ||
return root.load(filename, callback); | ||
} | ||
// function load(filename:string, root:Root, callback:LoadCallback):undefined | ||
// Parser | ||
protobuf.tokenize = require("./tokenize"); | ||
protobuf.parse = require("./parse"); | ||
protobuf.common = require("./common"); | ||
/** | ||
* Loads one or multiple .proto or preprocessed .json files into a common root namespace and calls the callback. | ||
* @name load | ||
* @function | ||
* @param {string|string[]} filename One or multiple files to load | ||
* @param {LoadCallback} callback Callback function | ||
* @returns {undefined} | ||
* @see {@link Root#load} | ||
* @variation 2 | ||
*/ | ||
// function load(filename:string, callback:LoadCallback):undefined | ||
/** | ||
* Loads one or multiple .proto or preprocessed .json files into a common root namespace and returns a promise. | ||
* @name load | ||
* @function | ||
* @param {string|string[]} filename One or multiple files to load | ||
* @param {Root} [root] Root namespace, defaults to create a new one if omitted. | ||
* @returns {Promise<Root>} Promise | ||
* @see {@link Root#load} | ||
* @variation 3 | ||
*/ | ||
// function load(filename:string, [root:Root]):Promise<Root> | ||
protobuf.load = load; | ||
/** | ||
* Synchronously loads one or multiple .proto or preprocessed .json files into a common root namespace (node only). | ||
* @param {string|string[]} filename One or multiple files to load | ||
* @param {Root} [root] Root namespace, defaults to create a new one if omitted. | ||
* @returns {Root} Root namespace | ||
* @throws {Error} If synchronous fetching is not supported (i.e. in browsers) or if a file's syntax is invalid | ||
* @see {@link Root#loadSync} | ||
*/ | ||
function loadSync(filename, root) { | ||
if (!root) | ||
root = new protobuf.Root(); | ||
return root.loadSync(filename); | ||
} | ||
protobuf.loadSync = loadSync; | ||
/** | ||
* Named roots. | ||
* This is where pbjs stores generated structures (the option `-r, --root` specifies a name). | ||
* Can also be used manually to make roots available accross modules. | ||
* @name roots | ||
* @type {Object.<string,Root>} | ||
*/ | ||
protobuf.roots = {}; | ||
// Parser (if not excluded) | ||
try { | ||
protobuf.tokenize = require("./tokenize"); | ||
protobuf.parse = require("./parse"); | ||
protobuf.common = require("./common"); | ||
} catch (e) {} // eslint-disable-line no-empty | ||
// Serialization | ||
protobuf.Writer = require("./writer"); | ||
protobuf.BufferWriter = require("./writer_buffer"); | ||
protobuf.Reader = require("./reader"); | ||
protobuf.BufferReader = require("./reader_buffer"); | ||
protobuf.encoder = require("./encoder"); | ||
protobuf.decoder = require("./decoder"); | ||
protobuf.verifier = require("./verifier"); | ||
protobuf.converter = require("./converter"); | ||
// Reflection | ||
protobuf.ReflectionObject = require("./object"); | ||
protobuf.Namespace = require("./namespace"); | ||
protobuf.Root = require("./root"); | ||
protobuf.Enum = require("./enum"); | ||
protobuf.Type = require("./type"); | ||
protobuf.Field = require("./field"); | ||
protobuf.OneOf = require("./oneof"); | ||
protobuf.MapField = require("./mapfield"); | ||
protobuf.Service = require("./service"); | ||
protobuf.Method = require("./method"); | ||
// Runtime | ||
protobuf.Class = require("./class"); | ||
protobuf.Message = require("./message"); | ||
// Utility | ||
protobuf.types = require("./types"); | ||
protobuf.rpc = require("./rpc"); | ||
protobuf.util = require("./util"); | ||
protobuf.configure = configure; | ||
/* istanbul ignore next */ | ||
/** | ||
* Reconfigures the library according to the environment. | ||
* @returns {undefined} | ||
*/ | ||
function configure() { | ||
protobuf.Reader._configure(); | ||
} | ||
/* istanbul ignore next */ | ||
if (typeof define === "function" && define.amd) | ||
define(["long"], function(Long) { | ||
if (Long) { | ||
protobuf.util.Long = Long; | ||
configure(); | ||
} | ||
return protobuf; | ||
}); | ||
protobuf.ReflectionObject._configure(protobuf.Root); | ||
protobuf.Namespace._configure(protobuf.Type, protobuf.Service); | ||
protobuf.Root._configure(protobuf.Type, protobuf.parse, protobuf.common); |
@@ -6,9 +6,4 @@ "use strict"; | ||
var Field = require("./field"); | ||
/** @alias Field.prototype */ | ||
var FieldPrototype = Field.prototype; | ||
/** @alias MapField.prototype */ | ||
var MapFieldPrototype = Field.extend(MapField); | ||
((MapField.prototype = Object.create(Field.prototype)).constructor = MapField).className = "MapField"; | ||
MapField.className = "MapField"; | ||
var types = require("./types"), | ||
@@ -52,11 +47,2 @@ util = require("./util"); | ||
/** | ||
* Tests if the specified JSON object describes a map field. | ||
* @param {*} json JSON object to test | ||
* @returns {boolean} `true` if the object describes a field | ||
*/ | ||
MapField.testJSON = function testJSON(json) { | ||
return Field.testJSON(json) && json.keyType !== undefined; | ||
}; | ||
/** | ||
* Constructs a map field from JSON. | ||
@@ -75,3 +61,3 @@ * @param {string} name Field name | ||
*/ | ||
MapFieldPrototype.toJSON = function toJSON() { | ||
MapField.prototype.toJSON = function toJSON() { | ||
return { | ||
@@ -89,3 +75,3 @@ keyType : this.keyType, | ||
*/ | ||
MapFieldPrototype.resolve = function resolve() { | ||
MapField.prototype.resolve = function resolve() { | ||
if (this.resolved) | ||
@@ -98,3 +84,3 @@ return this; | ||
return FieldPrototype.resolve.call(this); | ||
return Field.prototype.resolve.call(this); | ||
}; |
@@ -16,7 +16,5 @@ "use strict"; | ||
function Message(properties) { | ||
if (properties) { | ||
var keys = Object.keys(properties); | ||
for (var i = 0; i < keys.length; ++i) | ||
if (properties) | ||
for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) | ||
this[keys[i]] = properties[keys[i]]; | ||
} | ||
} | ||
@@ -23,0 +21,0 @@ |
@@ -6,10 +6,6 @@ "use strict"; | ||
var ReflectionObject = require("./object"); | ||
/** @alias Method.prototype */ | ||
var MethodPrototype = ReflectionObject.extend(Method); | ||
((Method.prototype = Object.create(ReflectionObject.prototype)).constructor = Method).className = "Method"; | ||
Method.className = "Method"; | ||
var util = require("./util"); | ||
var Type = require("./type"), | ||
util = require("./util"); | ||
/** | ||
@@ -29,2 +25,3 @@ * Constructs a new service method instance. | ||
function Method(name, type, requestType, responseType, requestStream, responseStream, options) { | ||
/* istanbul ignore next */ | ||
@@ -41,3 +38,3 @@ if (util.isObject(requestStream)) { | ||
/* istanbul ignore next */ | ||
if (type && !util.isString(type)) | ||
if (!(type === undefined || util.isString(type))) | ||
throw TypeError("type must be a string"); | ||
@@ -97,11 +94,2 @@ /* istanbul ignore next */ | ||
/** | ||
* Tests if the specified JSON object describes a service method. | ||
* @param {*} json JSON object | ||
* @returns {boolean} `true` if the object describes a map field | ||
*/ | ||
Method.testJSON = function testJSON(json) { | ||
return Boolean(json && json.requestType !== undefined); | ||
}; | ||
/** | ||
* Constructs a service method from JSON. | ||
@@ -120,3 +108,3 @@ * @param {string} name Method name | ||
*/ | ||
MethodPrototype.toJSON = function toJSON() { | ||
Method.prototype.toJSON = function toJSON() { | ||
return { | ||
@@ -135,14 +123,12 @@ type : this.type !== "rpc" && /* istanbul ignore next */ this.type || undefined, | ||
*/ | ||
MethodPrototype.resolve = function resolve() { | ||
Method.prototype.resolve = function resolve() { | ||
/* istanbul ignore if */ | ||
if (this.resolved) | ||
return this; | ||
/* istanbul ignore next */ | ||
if (!(this.resolvedRequestType = this.parent.lookup(this.requestType, Type))) | ||
throw Error("unresolvable request type: " + this.requestType); | ||
/* istanbul ignore next */ | ||
if (!(this.resolvedResponseType = this.parent.lookup(this.responseType, Type))) | ||
throw Error("unresolvable response type: " + this.requestType); | ||
this.resolvedRequestType = this.parent.lookupType(this.requestType); | ||
this.resolvedResponseType = this.parent.lookupType(this.responseType); | ||
return ReflectionObject.prototype.resolve.call(this); | ||
}; |
@@ -6,30 +6,11 @@ "use strict"; | ||
var ReflectionObject = require("./object"); | ||
/** @alias NamespaceBase.prototype */ | ||
var NamespacePrototype = ReflectionObject.extend(Namespace); | ||
((Namespace.prototype = Object.create(ReflectionObject.prototype)).constructor = Namespace).className = "Namespace"; | ||
Namespace.className = "Namespace"; | ||
var Enum = require("./enum"), | ||
Field = require("./field"), | ||
util = require("./util"); | ||
var Enum = require("./enum"), | ||
Field = require("./field"), | ||
util = require("./util"); | ||
var Type, // cyclic | ||
Service; // cyclic | ||
Service; // " | ||
var nestedTypes, // contains cyclics | ||
nestedError; | ||
function initNested() { | ||
/* istanbul ignore next */ | ||
if (!Type) | ||
Type = require("./type"); | ||
/* istanbul ignore next */ | ||
if (!Service) | ||
Service = require("./service"); | ||
nestedTypes = [ Enum, Type, Service, Field, Namespace ]; | ||
nestedError = "one of " + nestedTypes.map(function(ctor) { return ctor.name; }).join(", "); | ||
} | ||
/** | ||
@@ -46,19 +27,2 @@ * Constructs a new namespace instance. | ||
/** | ||
* Tests if the specified JSON object describes not another reflection object. | ||
* @memberof Namespace | ||
* @param {*} json JSON object | ||
* @returns {boolean} `true` if the object describes not another reflection object | ||
*/ | ||
Namespace.testJSON = function testJSON(json) { | ||
return Boolean(json | ||
&& !json.fields // Type | ||
&& !json.values // Enum | ||
&& json.id === undefined // Field, MapField | ||
&& !json.oneof // OneOf | ||
&& !json.methods // Service | ||
&& json.requestType === undefined // Method | ||
); | ||
}; | ||
/** | ||
* Constructs a namespace from JSON. | ||
@@ -119,9 +83,2 @@ * @memberof Namespace | ||
this._nestedArray = null; | ||
/** | ||
* Properties to remove when cache is cleared. | ||
* @type {Array.<string>} | ||
* @private | ||
*/ | ||
this._clearProperties = []; | ||
} | ||
@@ -131,5 +88,2 @@ | ||
namespace._nestedArray = null; | ||
for (var i = 0; i < namespace._clearProperties.length; ++i) | ||
delete namespace[namespace._clearProperties[i]]; | ||
namespace._clearProperties = []; | ||
return namespace; | ||
@@ -144,3 +98,3 @@ } | ||
*/ | ||
Object.defineProperty(NamespacePrototype, "nestedArray", { | ||
Object.defineProperty(Namespace.prototype, "nestedArray", { | ||
get: function() { | ||
@@ -154,3 +108,3 @@ return this._nestedArray || (this._nestedArray = util.toArray(this.nested)); | ||
*/ | ||
NamespacePrototype.toJSON = function toJSON() { | ||
Namespace.prototype.toJSON = function toJSON() { | ||
return { | ||
@@ -167,16 +121,20 @@ options : this.options, | ||
*/ | ||
NamespacePrototype.addJSON = function addJSON(nestedJson) { | ||
Namespace.prototype.addJSON = function addJSON(nestedJson) { | ||
var ns = this; | ||
/* istanbul ignore else */ | ||
if (nestedJson) { | ||
if (!nestedTypes) | ||
initNested(); | ||
Object.keys(nestedJson).forEach(function(nestedName) { | ||
var nested = nestedJson[nestedName]; | ||
for (var j = 0; j < nestedTypes.length; ++j) | ||
if (nestedTypes[j].testJSON(nested)) | ||
return ns.add(nestedTypes[j].fromJSON(nestedName, nested)); | ||
/* istanbul ignore next */ | ||
throw TypeError("nested." + nestedName + " must be JSON for " + nestedError); | ||
}); | ||
for (var names = Object.keys(nestedJson), i = 0, nested; i < names.length; ++i) { | ||
nested = nestedJson[names[i]]; | ||
ns.add( // most to least likely | ||
( nested.fields !== undefined | ||
? Type.fromJSON | ||
: nested.values !== undefined | ||
? Enum.fromJSON | ||
: nested.methods !== undefined | ||
? Service.fromJSON | ||
: nested.id !== undefined | ||
? Field.fromJSON | ||
: Namespace.fromJSON )(names[i], nested) | ||
); | ||
} | ||
} | ||
@@ -191,6 +149,5 @@ return this; | ||
*/ | ||
NamespacePrototype.get = function get(name) { | ||
if (this.nested === undefined) // prevents deopt | ||
return null; | ||
return this.nested[name] || null; | ||
Namespace.prototype.get = function get(name) { | ||
return this.nested && this.nested[name] | ||
|| null; | ||
}; | ||
@@ -205,3 +162,3 @@ | ||
*/ | ||
NamespacePrototype.getEnum = function getEnum(name) { | ||
Namespace.prototype.getEnum = function getEnum(name) { | ||
if (this.nested && this.nested[name] instanceof Enum) | ||
@@ -219,13 +176,7 @@ return this.nested[name].values; | ||
*/ | ||
NamespacePrototype.add = function add(object) { | ||
/* istanbul ignore next */ | ||
if (!nestedTypes) | ||
initNested(); | ||
/* istanbul ignore next */ | ||
if (!object || nestedTypes.indexOf(object.constructor) < 0) | ||
throw TypeError("object must be " + nestedError); | ||
/* istanbul ignore next */ | ||
if (object instanceof Field && object.extend === undefined) | ||
throw TypeError("object must be an extension field when not part of a type"); | ||
Namespace.prototype.add = function add(object) { | ||
if (!(object instanceof Field && object.extend !== undefined || object instanceof Type || object instanceof Enum || object instanceof Service || object instanceof Namespace)) | ||
throw TypeError("object must be a valid nested object"); | ||
if (!this.nested) | ||
@@ -236,4 +187,2 @@ this.nested = {}; | ||
if (prev) { | ||
// initNested above already initializes Type and Service | ||
/* istanbul ignore else */ | ||
if (prev instanceof Namespace && object instanceof Namespace && !(prev instanceof Type || prev instanceof Service)) { | ||
@@ -265,9 +214,7 @@ // replace plain namespace but keep existing nested elements and options | ||
*/ | ||
NamespacePrototype.remove = function remove(object) { | ||
Namespace.prototype.remove = function remove(object) { | ||
/* istanbul ignore next */ | ||
if (!(object instanceof ReflectionObject)) | ||
throw TypeError("object must be a ReflectionObject"); | ||
/* istanbul ignore next */ | ||
if (object.parent !== this || !this.nested) | ||
if (object.parent !== this) | ||
throw Error(object + " is not a member of " + this); | ||
@@ -278,2 +225,3 @@ | ||
this.nested = undefined; | ||
object.onRemove(this); | ||
@@ -289,8 +237,7 @@ return clearCache(this); | ||
*/ | ||
NamespacePrototype.define = function define(path, json) { | ||
Namespace.prototype.define = function define(path, json) { | ||
if (util.isString(path)) { | ||
if (util.isString(path)) | ||
path = path.split("."); | ||
/* istanbul ignore next */ | ||
} else if (!Array.isArray(path)) | ||
else if (!Array.isArray(path)) | ||
throw TypeError("illegal path"); | ||
@@ -305,3 +252,2 @@ if (path && path.length && path[0] === "") | ||
ptr = ptr.nested[part]; | ||
/* istanbul ignore next */ | ||
if (!(ptr instanceof Namespace)) | ||
@@ -318,36 +264,6 @@ throw Error("path conflicts with non-namespace objects"); | ||
/** | ||
* @override | ||
*/ | ||
NamespacePrototype.resolve = function resolve() { | ||
/* istanbul ignore next */ | ||
if (!Type) | ||
Type = require("./type"); | ||
/* istanbul ignore next */ | ||
if (!Service) | ||
Type = require("./service"); | ||
// Add uppercased (and thus conflict-free) nested types, services and enums as properties | ||
// of the type just like static code does. This allows using a .d.ts generated for a static | ||
// module with reflection-based solutions where the condition is met. | ||
var nested = this.nestedArray; | ||
for (var i = 0; i < nested.length; ++i) | ||
if (/^[A-Z]/.test(nested[i].name)) { | ||
if (nested[i] instanceof Type || nested[i] instanceof Service) | ||
this[nested[i].name] = nested[i]; | ||
else /* istanbul ignore else */ if (nested[i] instanceof Enum) | ||
this[nested[i].name] = nested[i].values; | ||
else | ||
continue; | ||
this._clearProperties.push(nested[i].name); | ||
} | ||
return ReflectionObject.prototype.resolve.call(this); | ||
}; | ||
/** | ||
* Resolves this namespace's and all its nested objects' type references. Useful to validate a reflection tree. | ||
* Resolves this namespace's and all its nested objects' type references. Useful to validate a reflection tree, but comes at a cost. | ||
* @returns {Namespace} `this` | ||
*/ | ||
NamespacePrototype.resolveAll = function resolveAll() { | ||
Namespace.prototype.resolveAll = function resolveAll() { | ||
var nested = this.nestedArray, i = 0; | ||
@@ -359,3 +275,3 @@ while (i < nested.length) | ||
nested[i++].resolve(); | ||
return NamespacePrototype.resolve.call(this); | ||
return this.resolve(); | ||
}; | ||
@@ -370,3 +286,3 @@ | ||
*/ | ||
NamespacePrototype.lookup = function lookup(path, filterType, parentAlreadyChecked) { | ||
Namespace.prototype.lookup = function lookup(path, filterType, parentAlreadyChecked) { | ||
@@ -422,8 +338,3 @@ /* istanbul ignore next */ | ||
*/ | ||
NamespacePrototype.lookupType = function lookupType(path) { | ||
/* istanbul ignore next */ | ||
if (!Type) | ||
Type = require("./type"); | ||
Namespace.prototype.lookupType = function lookupType(path) { | ||
var found = this.lookup(path, Type); | ||
@@ -442,8 +353,3 @@ if (!found) | ||
*/ | ||
NamespacePrototype.lookupService = function lookupService(path) { | ||
/* istanbul ignore next */ | ||
if (!Service) | ||
Service = require("./service"); | ||
Namespace.prototype.lookupService = function lookupService(path) { | ||
var found = this.lookup(path, Service); | ||
@@ -462,3 +368,3 @@ if (!found) | ||
*/ | ||
NamespacePrototype.lookupEnum = function lookupEnum(path) { | ||
Namespace.prototype.lookupEnum = function lookupEnum(path) { | ||
var found = this.lookup(path, Enum); | ||
@@ -469,1 +375,6 @@ if (!found) | ||
}; | ||
Namespace._configure = function(Type_, Service_) { | ||
Type = Type_; | ||
Service = Service_; | ||
}; |
"use strict"; | ||
module.exports = ReflectionObject; | ||
ReflectionObject.className = "ReflectionObject"; | ||
var util = require("./util"); | ||
ReflectionObject.className = "ReflectionObject"; | ||
ReflectionObject.extend = util.extend; | ||
var Root; // cyclic | ||
@@ -23,2 +22,3 @@ | ||
throw TypeError("name must be a string"); | ||
if (options && !util.isObject(options)) | ||
@@ -58,7 +58,4 @@ throw TypeError("options must be an object"); | ||
/** @alias ReflectionObject.prototype */ | ||
var ReflectionObjectPrototype = ReflectionObject.prototype; | ||
Object.defineProperties(ReflectionObject.prototype, { | ||
Object.defineProperties(ReflectionObjectPrototype, { | ||
/** | ||
@@ -103,3 +100,3 @@ * Reference to the root namespace. | ||
*/ | ||
ReflectionObjectPrototype.toJSON = /* istanbul ignore next */ function toJSON() { | ||
ReflectionObject.prototype.toJSON = /* istanbul ignore next */ function toJSON() { | ||
throw Error(); // not implemented, shouldn't happen | ||
@@ -113,3 +110,3 @@ }; | ||
*/ | ||
ReflectionObjectPrototype.onAdd = function onAdd(parent) { | ||
ReflectionObject.prototype.onAdd = function onAdd(parent) { | ||
if (this.parent && this.parent !== parent) | ||
@@ -120,4 +117,2 @@ this.parent.remove(this); | ||
var root = parent.root; | ||
if (!Root) | ||
Root = require("./root"); | ||
if (root instanceof Root) | ||
@@ -132,8 +127,3 @@ root._handleAdd(this); | ||
*/ | ||
ReflectionObjectPrototype.onRemove = function onRemove(parent) { | ||
/* istanbul ignore next */ | ||
if (!Root) | ||
Root = require("./root"); | ||
ReflectionObject.prototype.onRemove = function onRemove(parent) { | ||
var root = parent.root; | ||
@@ -150,10 +140,5 @@ if (root instanceof Root) | ||
*/ | ||
ReflectionObjectPrototype.resolve = function resolve() { | ||
ReflectionObject.prototype.resolve = function resolve() { | ||
if (this.resolved) | ||
return this; | ||
/* istanbul ignore next */ | ||
if (!Root) | ||
Root = require("./root"); | ||
if (this.root instanceof Root) | ||
@@ -169,3 +154,3 @@ this.resolved = true; // only if part of a root | ||
*/ | ||
ReflectionObjectPrototype.getOption = function getOption(name) { | ||
ReflectionObject.prototype.getOption = function getOption(name) { | ||
if (this.options) | ||
@@ -183,3 +168,3 @@ return this.options[name]; | ||
*/ | ||
ReflectionObjectPrototype.setOption = function setOption(name, value, ifNotSet) { | ||
ReflectionObject.prototype.setOption = function setOption(name, value, ifNotSet) { | ||
if (!ifNotSet || !this.options || this.options[name] === undefined) | ||
@@ -196,7 +181,6 @@ (this.options || (this.options = {}))[name] = value; | ||
*/ | ||
ReflectionObjectPrototype.setOptions = function setOptions(options, ifNotSet) { | ||
ReflectionObject.prototype.setOptions = function setOptions(options, ifNotSet) { | ||
if (options) | ||
Object.keys(options).forEach(function(name) { | ||
this.setOption(name, options[name], ifNotSet); | ||
}, this); | ||
for (var keys = Object.keys(options), i = 0; i < keys.length; ++i) | ||
this.setOption(keys[i], options[keys[i]], ifNotSet); | ||
return this; | ||
@@ -209,3 +193,3 @@ }; | ||
*/ | ||
ReflectionObjectPrototype.toString = function toString() { | ||
ReflectionObject.prototype.toString = function toString() { | ||
var className = this.constructor.className, | ||
@@ -217,1 +201,5 @@ fullName = this.fullName; | ||
}; | ||
ReflectionObject._configure = function(Root_) { | ||
Root = Root_; | ||
}; |
@@ -6,7 +6,4 @@ "use strict"; | ||
var ReflectionObject = require("./object"); | ||
/** @alias OneOf.prototype */ | ||
var OneOfPrototype = ReflectionObject.extend(OneOf); | ||
((OneOf.prototype = Object.create(ReflectionObject.prototype)).constructor = OneOf).className = "OneOf"; | ||
OneOf.className = "OneOf"; | ||
var Field = require("./field"); | ||
@@ -31,3 +28,3 @@ | ||
/* istanbul ignore next */ | ||
if (fieldNames && !Array.isArray(fieldNames)) | ||
if (!(fieldNames === undefined || Array.isArray(fieldNames))) | ||
throw TypeError("fieldNames must be an Array"); | ||
@@ -42,31 +39,10 @@ | ||
/** | ||
* Fields that belong to this oneof and are possibly not yet added to its parent. | ||
* Fields that belong to this oneof as an array for iteration. | ||
* @type {Field[]} | ||
* @private | ||
* @readonly | ||
*/ | ||
this._fieldsArray = []; | ||
this.fieldsArray = []; // declared readonly for conformance, possibly not yet added to parent | ||
} | ||
/** | ||
* Fields that belong to this oneof as an array for iteration. | ||
* @name OneOf#fieldsArray | ||
* @type {Field[]} | ||
* @readonly | ||
*/ | ||
Object.defineProperty(OneOfPrototype, "fieldsArray", { | ||
get: function() { | ||
return this._fieldsArray; | ||
} | ||
}); | ||
/** | ||
* Tests if the specified JSON object describes a oneof. | ||
* @param {*} json JSON object | ||
* @returns {boolean} `true` if the object describes a oneof | ||
*/ | ||
OneOf.testJSON = function testJSON(json) { | ||
return Boolean(json.oneof); | ||
}; | ||
/** | ||
* Constructs a oneof from JSON. | ||
@@ -85,3 +61,3 @@ * @param {string} name Oneof name | ||
*/ | ||
OneOfPrototype.toJSON = function toJSON() { | ||
OneOf.prototype.toJSON = function toJSON() { | ||
return { | ||
@@ -101,8 +77,6 @@ oneof : this.oneof, | ||
function addFieldsToParent(oneof) { | ||
if (oneof.parent) { | ||
oneof._fieldsArray.forEach(function(field) { | ||
if (!field.parent) | ||
oneof.parent.add(field); | ||
}); | ||
} | ||
if (oneof.parent) | ||
for (var i = 0; i < oneof.fieldsArray.length; ++i) | ||
if (!oneof.fieldsArray[i].parent) | ||
oneof.parent.add(oneof.fieldsArray[i]); | ||
} | ||
@@ -115,3 +89,3 @@ | ||
*/ | ||
OneOfPrototype.add = function add(field) { | ||
OneOf.prototype.add = function add(field) { | ||
@@ -124,3 +98,3 @@ /* istanbul ignore next */ | ||
this.oneof.push(field.name); | ||
this._fieldsArray.push(field); | ||
this.fieldsArray.push(field); | ||
field.partOf = this; // field.parent remains null | ||
@@ -136,3 +110,3 @@ addFieldsToParent(this); | ||
*/ | ||
OneOfPrototype.remove = function remove(field) { | ||
OneOf.prototype.remove = function remove(field) { | ||
@@ -143,3 +117,3 @@ /* istanbul ignore next */ | ||
var index = this._fieldsArray.indexOf(field); | ||
var index = this.fieldsArray.indexOf(field); | ||
/* istanbul ignore next */ | ||
@@ -149,3 +123,3 @@ if (index < 0) | ||
this._fieldsArray.splice(index, 1); | ||
this.fieldsArray.splice(index, 1); | ||
index = this.oneof.indexOf(field.name); | ||
@@ -162,13 +136,13 @@ /* istanbul ignore else */ | ||
*/ | ||
OneOfPrototype.onAdd = function onAdd(parent) { | ||
OneOf.prototype.onAdd = function onAdd(parent) { | ||
ReflectionObject.prototype.onAdd.call(this, parent); | ||
var self = this; | ||
// Collect present fields | ||
this.oneof.forEach(function(fieldName) { | ||
var field = parent.get(fieldName); | ||
for (var i = 0; i < this.oneof.length; ++i) { | ||
var field = parent.get(this.oneof[i]); | ||
if (field && !field.partOf) { | ||
field.partOf = self; | ||
self._fieldsArray.push(field); | ||
self.fieldsArray.push(field); | ||
} | ||
}); | ||
} | ||
// Add not yet present fields | ||
@@ -181,8 +155,7 @@ addFieldsToParent(this); | ||
*/ | ||
OneOfPrototype.onRemove = function onRemove(parent) { | ||
this._fieldsArray.forEach(function(field) { | ||
if (field.parent) | ||
OneOf.prototype.onRemove = function onRemove(parent) { | ||
for (var i = 0, field; i < this.fieldsArray.length; ++i) | ||
if ((field = this.fieldsArray[i]).parent) | ||
field.parent.remove(field); | ||
}); | ||
ReflectionObject.prototype.onRemove.call(this, parent); | ||
}; |
@@ -497,20 +497,24 @@ "use strict"; | ||
function parseOptionValue(parent, name) { | ||
if (skip("{", true)) { | ||
while ((token = next()) !== "}") { | ||
/* istanbul ignore next */ | ||
if (!isName(token)) | ||
if (skip("{", true)) { // { a: "foo" b { c: "bar" } } | ||
/* istanbul ignore next */ | ||
do { | ||
if (!isName(token = next())) | ||
throw illegal(token, "name"); | ||
skip(":"); | ||
// if (skip(":", true)) | ||
parent.setOption(name + "." + token, readValue(true)); | ||
// else | ||
// parseOptionValue(parent, name + "." + token); | ||
} | ||
if (peek() === "{") | ||
parseOptionValue(parent, name + "." + token); | ||
else { | ||
skip(":"); | ||
setOption(parent, name + "." + token, readValue(true)); | ||
} | ||
} while (!skip("}", true)); | ||
} else | ||
parent.setOption(name, readValue(true)); | ||
setOption(parent, name, readValue(true)); | ||
// Does not enforce a delimiter to be universal | ||
} | ||
function setOption(parent, name, value) { | ||
if (parent.setOption) | ||
parent.setOption(name, value); | ||
} | ||
function parseInlineOptions(parent) { | ||
@@ -517,0 +521,0 @@ if (skip("[", true)) { |
@@ -6,7 +6,5 @@ "use strict"; | ||
var Reader = require("./reader"); | ||
/** @alias BufferReader.prototype */ | ||
var BufferReaderPrototype = BufferReader.prototype = Object.create(Reader.prototype); | ||
BufferReaderPrototype.constructor = BufferReader; | ||
(BufferReader.prototype = Object.create(Reader.prototype)).constructor = BufferReader; | ||
var util = require("./util/runtime"); | ||
var util = require("./util/minimal"); | ||
@@ -26,3 +24,3 @@ /** | ||
if (util.Buffer) | ||
BufferReaderPrototype._slice = util.Buffer.prototype.slice; | ||
BufferReader.prototype._slice = util.Buffer.prototype.slice; | ||
@@ -32,5 +30,5 @@ /** | ||
*/ | ||
BufferReaderPrototype.string = function read_string_buffer() { | ||
BufferReader.prototype.string = function read_string_buffer() { | ||
var len = this.uint32(); // modifies pos | ||
return this.buf.utf8Slice(this.pos, this.pos = Math.min(this.pos + len, this.len)); | ||
}; |
"use strict"; | ||
module.exports = Reader; | ||
var util = require("./util/runtime"); | ||
var util = require("./util/minimal"); | ||
@@ -51,5 +51,2 @@ var BufferReader; // cyclic | ||
? function create_buffer_setup(buffer) { | ||
/* istanbul ignore next */ | ||
if (!BufferReader) | ||
BufferReader = require("./reader_buffer"); | ||
return (Reader.create = function create_buffer(buffer) { | ||
@@ -66,7 +63,4 @@ return util.Buffer.isBuffer(buffer) | ||
/** @alias Reader.prototype */ | ||
var ReaderPrototype = Reader.prototype; | ||
Reader.prototype._slice = util.Array.prototype.subarray || /* istanbul ignore next */ util.Array.prototype.slice; | ||
ReaderPrototype._slice = util.Array.prototype.subarray || /* istanbul ignore next */ util.Array.prototype.slice; | ||
/** | ||
@@ -77,3 +71,3 @@ * Reads a varint as an unsigned 32 bit value. | ||
*/ | ||
ReaderPrototype.uint32 = (function read_uint32_setup() { | ||
Reader.prototype.uint32 = (function read_uint32_setup() { | ||
var value = 4294967295; // optimizer type-hint, tends to deopt otherwise (?!) | ||
@@ -100,3 +94,3 @@ return function read_uint32() { | ||
*/ | ||
ReaderPrototype.int32 = function read_int32() { | ||
Reader.prototype.int32 = function read_int32() { | ||
return this.uint32() | 0; | ||
@@ -109,3 +103,3 @@ }; | ||
*/ | ||
ReaderPrototype.sint32 = function read_sint32() { | ||
Reader.prototype.sint32 = function read_sint32() { | ||
var value = this.uint32(); | ||
@@ -224,3 +218,3 @@ return value >>> 1 ^ -(value & 1) | 0; | ||
*/ | ||
ReaderPrototype.bool = function read_bool() { | ||
Reader.prototype.bool = function read_bool() { | ||
return this.uint32() !== 0; | ||
@@ -240,3 +234,3 @@ }; | ||
*/ | ||
ReaderPrototype.fixed32 = function read_fixed32() { | ||
Reader.prototype.fixed32 = function read_fixed32() { | ||
@@ -254,3 +248,3 @@ /* istanbul ignore next */ | ||
*/ | ||
ReaderPrototype.sfixed32 = function read_sfixed32() { | ||
Reader.prototype.sfixed32 = function read_sfixed32() { | ||
var value = this.fixed32(); | ||
@@ -347,3 +341,3 @@ return value >>> 1 ^ -(value & 1); | ||
*/ | ||
ReaderPrototype.float = function read_float() { | ||
Reader.prototype.float = function read_float() { | ||
@@ -410,3 +404,3 @@ /* istanbul ignore next */ | ||
*/ | ||
ReaderPrototype.double = function read_double() { | ||
Reader.prototype.double = function read_double() { | ||
@@ -426,3 +420,3 @@ /* istanbul ignore next */ | ||
*/ | ||
ReaderPrototype.bytes = function read_bytes() { | ||
Reader.prototype.bytes = function read_bytes() { | ||
var length = this.uint32(), | ||
@@ -446,3 +440,3 @@ start = this.pos, | ||
*/ | ||
ReaderPrototype.string = function read_string() { | ||
Reader.prototype.string = function read_string() { | ||
var bytes = this.bytes(); | ||
@@ -457,3 +451,3 @@ return utf8.read(bytes, 0, bytes.length); | ||
*/ | ||
ReaderPrototype.skip = function skip(length) { | ||
Reader.prototype.skip = function skip(length) { | ||
if (typeof length === "number") { | ||
@@ -479,3 +473,3 @@ /* istanbul ignore next */ | ||
*/ | ||
ReaderPrototype.skipType = function(wireType) { | ||
Reader.prototype.skipType = function(wireType) { | ||
switch (wireType) { | ||
@@ -509,21 +503,19 @@ case 0: | ||
function configure() { | ||
Reader._configure = function(BufferReader_) { | ||
BufferReader = BufferReader_; | ||
/* istanbul ignore else */ | ||
if (util.Long) { | ||
ReaderPrototype.int64 = read_int64_long; | ||
ReaderPrototype.uint64 = read_uint64_long; | ||
ReaderPrototype.sint64 = read_sint64_long; | ||
ReaderPrototype.fixed64 = read_fixed64_long; | ||
ReaderPrototype.sfixed64 = read_sfixed64_long; | ||
Reader.prototype.int64 = read_int64_long; | ||
Reader.prototype.uint64 = read_uint64_long; | ||
Reader.prototype.sint64 = read_sint64_long; | ||
Reader.prototype.fixed64 = read_fixed64_long; | ||
Reader.prototype.sfixed64 = read_sfixed64_long; | ||
} else { | ||
ReaderPrototype.int64 = read_int64_number; | ||
ReaderPrototype.uint64 = read_uint64_number; | ||
ReaderPrototype.sint64 = read_sint64_number; | ||
ReaderPrototype.fixed64 = read_fixed64_number; | ||
ReaderPrototype.sfixed64 = read_sfixed64_number; | ||
Reader.prototype.int64 = read_int64_number; | ||
Reader.prototype.uint64 = read_uint64_number; | ||
Reader.prototype.sint64 = read_sint64_number; | ||
Reader.prototype.fixed64 = read_fixed64_number; | ||
Reader.prototype.sfixed64 = read_sfixed64_number; | ||
} | ||
} | ||
Reader._configure = configure; | ||
configure(); | ||
}; |
153
src/root.js
@@ -6,13 +6,12 @@ "use strict"; | ||
var Namespace = require("./namespace"); | ||
/** @alias Root.prototype */ | ||
var RootPrototype = Namespace.extend(Root); | ||
((Root.prototype = Object.create(Namespace.prototype)).constructor = Root).className = "Root"; | ||
Root.className = "Root"; | ||
var Field = require("./field"), | ||
Enum = require("./enum"), | ||
util = require("./util"); | ||
var Field = require("./field"), | ||
util = require("./util"); | ||
var Type, // cyclic | ||
parse, // might be excluded | ||
common; // " | ||
var parse, // cyclic, might be excluded | ||
common; // might be excluded | ||
/** | ||
@@ -50,3 +49,5 @@ * Constructs a new root namespace instance. | ||
root = new Root(); | ||
return root.setOptions(json.options).addJSON(json.nested); | ||
if (json.options) | ||
root.setOptions(json.options); | ||
return root.addJSON(json.nested); | ||
}; | ||
@@ -62,3 +63,3 @@ | ||
*/ | ||
RootPrototype.resolvePath = util.path.resolve; | ||
Root.prototype.resolvePath = util.path.resolve; | ||
@@ -69,10 +70,2 @@ // A symbol-like function to safely signal synchronous loading | ||
var initParser = function() { | ||
try { // excluded in noparse builds | ||
parse = require("./parse"); | ||
common = require("./common"); | ||
} catch (e) {} // eslint-disable-line no-empty | ||
initParser = null; | ||
}; | ||
/** | ||
@@ -85,5 +78,3 @@ * Loads one or multiple .proto or preprocessed .json files into this root namespace and calls the callback. | ||
*/ | ||
RootPrototype.load = function load(filename, options, callback) { | ||
if (initParser) | ||
initParser(); | ||
Root.prototype.load = function load(filename, options, callback) { | ||
if (typeof options === "function") { | ||
@@ -120,11 +111,10 @@ callback = options; | ||
parse.filename = filename; | ||
var parsed = parse(source, self, options); | ||
var parsed = parse(source, self, options), | ||
i = 0; | ||
if (parsed.imports) | ||
parsed.imports.forEach(function(name) { | ||
fetch(self.resolvePath(filename, name)); | ||
}); | ||
for (; i < parsed.imports.length; ++i) | ||
fetch(self.resolvePath(filename, parsed.imports[i])); | ||
if (parsed.weakImports) | ||
parsed.weakImports.forEach(function(name) { | ||
fetch(self.resolvePath(filename, name), true); | ||
}); | ||
for (i = 0; i < parsed.weakImports.length; ++i) | ||
fetch(self.resolvePath(filename, parsed.weakImports[i]), true); | ||
} | ||
@@ -203,5 +193,4 @@ } catch (err) { | ||
filename = [ filename ]; | ||
filename.forEach(function(filename) { | ||
fetch(self.resolvePath("", filename)); | ||
}); | ||
for (var i = 0; i < filename.length; ++i) | ||
fetch(self.resolvePath("", filename[i])); | ||
@@ -245,3 +234,3 @@ if (sync) | ||
*/ | ||
RootPrototype.loadSync = function loadSync(filename, options) { | ||
Root.prototype.loadSync = function loadSync(filename, options) { | ||
if (!util.isNode) | ||
@@ -255,3 +244,3 @@ throw Error("not supported"); | ||
*/ | ||
RootPrototype.resolveAll = function resolveAll() { | ||
Root.prototype.resolveAll = function resolveAll() { | ||
if (this.deferred.length) | ||
@@ -264,4 +253,8 @@ throw Error("unresolvable extensions: " + this.deferred.map(function(field) { | ||
// only uppercased (and thus conflict-free) children are exposed, see below | ||
var exposeRe = /^[A-Z]/; | ||
/** | ||
* Handles a deferred declaring extension field by creating a sister field to represent it within its extended type. | ||
* @param {Root} root Root instance | ||
* @param {Field} field Declaring extension field witin the declaring type | ||
@@ -272,3 +265,3 @@ * @returns {boolean} `true` if successfully added to the extended type, `false` otherwise | ||
*/ | ||
function handleExtension(field) { | ||
function tryHandleExtension(root, field) { | ||
var extendedType = field.parent.lookup(field.extend); | ||
@@ -291,21 +284,31 @@ if (extendedType) { | ||
*/ | ||
RootPrototype._handleAdd = function handleAdd(object) { | ||
// Try to handle any deferred extensions | ||
var newDeferred = this.deferred.slice(); | ||
this.deferred = []; // because the loop calls handleAdd | ||
var i = 0; | ||
while (i < newDeferred.length) | ||
if (handleExtension(newDeferred[i])) | ||
newDeferred.splice(i, 1); | ||
else | ||
++i; | ||
this.deferred = newDeferred; | ||
// Handle new declaring extension fields without a sister field yet | ||
if (object instanceof Field && object.extend !== undefined && !object.extensionField && !handleExtension(object) && this.deferred.indexOf(object) < 0) | ||
this.deferred.push(object); | ||
else if (object instanceof Namespace) { | ||
var nested = object.nestedArray; | ||
for (i = 0; i < nested.length; ++i) // recurse into the namespace | ||
this._handleAdd(nested[i]); | ||
Root.prototype._handleAdd = function _handleAdd(object) { | ||
if (object instanceof Field) { | ||
if (/* an extension field (implies not part of a oneof) */ object.extend !== undefined && /* not already handled */ !object.extensionField) | ||
if (!tryHandleExtension(this, object)) | ||
this.deferred.push(object); | ||
} else if (object instanceof Enum) { | ||
if (exposeRe.test(object.name)) | ||
object.parent[object.name] = object.values; // expose enum values as property of its parent | ||
} else /* everything else is a namespace */ { | ||
if (object instanceof Type) // Try to handle any deferred extensions | ||
for (var i = 0; i < this.deferred.length;) | ||
if (tryHandleExtension(this, this.deferred[i])) | ||
this.deferred.splice(i, 1); | ||
else | ||
++i; | ||
for (var j = 0; j < /* initializes */ object.nestedArray.length; ++j) // recurse into the namespace | ||
this._handleAdd(object._nestedArray[j]); | ||
if (exposeRe.test(object.name)) | ||
object.parent[object.name] = object; // expose namespace as property of its parent | ||
} | ||
// The above also adds uppercased (and thus conflict-free) nested types, services and enums as | ||
// properties of namespaces just like static code does. This allows using a .d.ts generated for | ||
// a static module with reflection-based solutions where the condition is met. | ||
}; | ||
@@ -319,21 +322,37 @@ | ||
*/ | ||
RootPrototype._handleRemove = function handleRemove(object) { | ||
Root.prototype._handleRemove = function _handleRemove(object) { | ||
if (object instanceof Field) { | ||
// If a deferred declaring extension field, cancel the extension | ||
if (object.extend !== undefined && !object.extensionField) { | ||
var index = this.deferred.indexOf(object); | ||
/* istanbul ignore else */ | ||
if (index > -1) | ||
this.deferred.splice(index, 1); | ||
if (/* an extension field */ object.extend !== undefined) { | ||
if (/* already handled */ object.extensionField) { // remove its sister field | ||
object.extensionField.parent.remove(object.extensionField); | ||
object.extensionField = null; | ||
} else { // cancel the extension | ||
var index = this.deferred.indexOf(object); | ||
/* istanbul ignore else */ | ||
if (index > -1) | ||
this.deferred.splice(index, 1); | ||
} | ||
} | ||
// If a declaring extension field with a sister field, remove its sister field | ||
if (object.extensionField) { | ||
object.extensionField.parent.remove(object.extensionField); | ||
object.extensionField = null; | ||
} | ||
} else if (object instanceof Enum) { | ||
if (exposeRe.test(object.name)) | ||
delete object.parent[object.name]; // unexpose enum values | ||
} else if (object instanceof Namespace) { | ||
var nested = object.nestedArray; | ||
for (var i = 0; i < nested.length; ++i) // recurse into the namespace | ||
this._handleRemove(nested[i]); | ||
for (var i = 0; i < /* initializes */ object.nestedArray.length; ++i) // recurse into the namespace | ||
this._handleRemove(object._nestedArray[i]); | ||
if (exposeRe.test(object.name)) | ||
delete object.parent[object.name]; // unexpose namespaces | ||
} | ||
}; | ||
Root._configure = function(Type_, parse_, common_) { | ||
Type = Type_; | ||
parse = parse_; | ||
common = common_; | ||
}; |
@@ -9,2 +9,29 @@ "use strict"; | ||
/** | ||
* RPC implementation passed to {@link Service#create} performing a service request on network level, i.e. by utilizing http requests or websockets. | ||
* @typedef RPCImpl | ||
* @type {function} | ||
* @param {Method|rpc.ServiceMethod} method Reflected or static method being called | ||
* @param {Uint8Array} requestData Request data | ||
* @param {RPCImplCallback} callback Callback function | ||
* @returns {undefined} | ||
* @example | ||
* function rpcImpl(method, requestData, callback) { | ||
* if (protobuf.util.lcFirst(method.name) !== "myMethod") // compatible with static code | ||
* throw Error("no such method"); | ||
* asynchronouslyObtainAResponse(requestData, function(err, responseData) { | ||
* callback(err, responseData); | ||
* }); | ||
* } | ||
*/ | ||
/** | ||
* Node-style callback as used by {@link RPCImpl}. | ||
* @typedef RPCImplCallback | ||
* @type {function} | ||
* @param {?Error} error Error, if any, otherwise `null` | ||
* @param {?Uint8Array} [response] Response data or `null` to signal end of stream, if there hasn't been an error | ||
* @returns {undefined} | ||
*/ | ||
rpc.Service = require("./rpc/service"); |
"use strict"; | ||
module.exports = Service; | ||
var EventEmitter = require("../util").EventEmitter; | ||
var util = require("../util/minimal"); | ||
// Extends EventEmitter | ||
(Service.prototype = Object.create(util.EventEmitter.prototype)).constructor = Service; | ||
/** | ||
* A service method callback as used by {@link rpc.ServiceMethod|ServiceMethod}. | ||
* | ||
* Differs from {@link RPCImplCallback} in that it is an actual callback of a service method which may not return `response = null`. | ||
* @typedef rpc.ServiceMethodCallback | ||
* @type {function} | ||
* @param {?Error} error Error, if any | ||
* @param {?Message} [response] Response message | ||
* @returns {undefined} | ||
*/ | ||
/** | ||
* A service method part of an {@link rpc.ServiceMethodMixin|ServiceMethodMixin} and thus {@link rpc.Service} as created by {@link Service.create}. | ||
* @typedef rpc.ServiceMethod | ||
* @type {function} | ||
* @param {Message|Object} request Request message or plain object | ||
* @param {rpc.ServiceMethodCallback} [callback] Node-style callback called with the error, if any, and the response message | ||
* @returns {Promise<Message>} Promise if `callback` has been omitted, otherwise `undefined` | ||
*/ | ||
/** | ||
* A service method mixin. | ||
* | ||
* When using TypeScript, mixed in service methods are only supported directly with a type definition of a static module (used with reflection). Otherwise, explicit casting is required. | ||
* @typedef rpc.ServiceMethodMixin | ||
* @type {Object.<string,rpc.ServiceMethod>} | ||
* @example | ||
* // Explicit casting with TypeScript | ||
* (myRpcService["myMethod"] as protobuf.rpc.ServiceMethod)(...) | ||
*/ | ||
/** | ||
* Constructs a new RPC service instance. | ||
@@ -11,8 +45,15 @@ * @classdesc An RPC service as returned by {@link Service#create}. | ||
* @extends util.EventEmitter | ||
* @augments rpc.ServiceMethodMixin | ||
* @constructor | ||
* @param {RPCImpl} rpcImpl RPC implementation | ||
* @param {boolean} [requestDelimited=false] Whether requests are length-delimited | ||
* @param {boolean} [responseDelimited=false] Whether responses are length-delimited | ||
*/ | ||
function Service(rpcImpl) { | ||
EventEmitter.call(this); | ||
function Service(rpcImpl, requestDelimited, responseDelimited) { | ||
if (typeof rpcImpl !== "function") | ||
throw TypeError("rpcImpl must be a function"); | ||
util.EventEmitter.call(this); | ||
/** | ||
@@ -22,7 +63,76 @@ * RPC implementation. Becomes `null` once the service is ended. | ||
*/ | ||
this.$rpc = rpcImpl; | ||
this.rpcImpl = rpcImpl; | ||
/** | ||
* Whether requests are length-delimited. | ||
* @type {boolean} | ||
*/ | ||
this.requestDelimited = Boolean(requestDelimited); | ||
/** | ||
* Whether responses are length-delimited. | ||
* @type {boolean} | ||
*/ | ||
this.responseDelimited = Boolean(responseDelimited); | ||
} | ||
(Service.prototype = Object.create(EventEmitter.prototype)).constructor = Service; | ||
/** | ||
* Calls a service method through {@link rpc.Service#rpcImpl|rpcImpl}. | ||
* @param {Method|rpc.ServiceMethod} method Reflected or static method | ||
* @param {function} requestCtor Request constructor | ||
* @param {function} responseCtor Response constructor | ||
* @param {Message|Object} request Request message or plain object | ||
* @param {rpc.ServiceMethodCallback} callback Service callback | ||
* @returns {undefined} | ||
*/ | ||
Service.prototype.rpcCall = function rpcCall(method, requestCtor, responseCtor, request, callback) { | ||
if (!request) | ||
throw TypeError("request must be specified"); | ||
var self = this; | ||
if (!callback) | ||
return util.asPromise(rpcCall, self, method, requestCtor, responseCtor, request); | ||
if (!self.rpcImpl) { | ||
setTimeout(function() { callback(Error("already ended")); }, 0); | ||
return undefined; | ||
} | ||
try { | ||
return self.rpcImpl( | ||
method, | ||
requestCtor[self.requestDelimited ? "encodeDelimited" : "encode"](request).finish(), | ||
function rpcCallback(err, response) { | ||
if (err) { | ||
self.emit("error", err, method); | ||
return callback(err); | ||
} | ||
if (response === null) { | ||
self.end(/* endedByRPC */ true); | ||
return undefined; | ||
} | ||
if (!(response instanceof responseCtor)) { | ||
try { | ||
response = responseCtor[self.responseDelimited ? "decodeDelimited" : "decode"](response); | ||
} catch (err) { | ||
self.emit("error", err, method); | ||
return callback("error", err); | ||
} | ||
} | ||
self.emit("data", response, method); | ||
return callback(null, response); | ||
} | ||
); | ||
} catch (err) { | ||
self.emit("error", err, method); | ||
setTimeout(function() { callback(err); }, 0); | ||
return undefined; | ||
} | ||
}; | ||
/** | ||
@@ -34,6 +144,6 @@ * Ends this service and emits the `end` event. | ||
Service.prototype.end = function end(endedByRPC) { | ||
if (this.$rpc) { | ||
if (this.rpcImpl) { | ||
if (!endedByRPC) // signal end to rpcImpl | ||
this.$rpc(null, null, null); | ||
this.$rpc = null; | ||
this.rpcImpl(null, null, null); | ||
this.rpcImpl = null; | ||
this.emit("end").off(); | ||
@@ -40,0 +150,0 @@ } |
@@ -6,9 +6,4 @@ "use strict"; | ||
var Namespace = require("./namespace"); | ||
/** @alias Namespace.prototype */ | ||
var NamespacePrototype = Namespace.prototype; | ||
/** @alias Service.prototype */ | ||
var ServicePrototype = Namespace.extend(Service); | ||
((Service.prototype = Object.create(Namespace.prototype)).constructor = Service).className = "Service"; | ||
Service.className = "Service"; | ||
var Method = require("./method"), | ||
@@ -45,11 +40,2 @@ util = require("./util"), | ||
/** | ||
* Tests if the specified JSON object describes a service. | ||
* @param {*} json JSON object to test | ||
* @returns {boolean} `true` if the object describes a service | ||
*/ | ||
Service.testJSON = function testJSON(json) { | ||
return Boolean(json && json.methods); | ||
}; | ||
/** | ||
* Constructs a service from JSON. | ||
@@ -65,5 +51,4 @@ * @param {string} name Service name | ||
if (json.methods) | ||
Object.keys(json.methods).forEach(function(methodName) { | ||
service.add(Method.fromJSON(methodName, json.methods[methodName])); | ||
}); | ||
for (var names = Object.keys(json.methods), i = 0; i < names.length; ++i) | ||
service.add(Method.fromJSON(names[i], json.methods[names[i]])); | ||
return service; | ||
@@ -78,3 +63,3 @@ }; | ||
*/ | ||
Object.defineProperty(ServicePrototype, "methodsArray", { | ||
Object.defineProperty(Service.prototype, "methodsArray", { | ||
get: function() { | ||
@@ -93,4 +78,4 @@ return this._methodsArray || (this._methodsArray = util.toArray(this.methods)); | ||
*/ | ||
ServicePrototype.toJSON = function toJSON() { | ||
var inherited = NamespacePrototype.toJSON.call(this); | ||
Service.prototype.toJSON = function toJSON() { | ||
var inherited = Namespace.prototype.toJSON.call(this); | ||
return { | ||
@@ -106,4 +91,5 @@ options : inherited && inherited.options || undefined, | ||
*/ | ||
ServicePrototype.get = function get(name) { | ||
return NamespacePrototype.get.call(this, name) || this.methods[name] || null; | ||
Service.prototype.get = function get(name) { | ||
return this.methods[name] | ||
|| Namespace.prototype.get.call(this, name); | ||
}; | ||
@@ -114,7 +100,7 @@ | ||
*/ | ||
ServicePrototype.resolveAll = function resolveAll() { | ||
Service.prototype.resolveAll = function resolveAll() { | ||
var methods = this.methodsArray; | ||
for (var i = 0; i < methods.length; ++i) | ||
methods[i].resolve(); | ||
return NamespacePrototype.resolve.call(this); | ||
return Namespace.prototype.resolve.call(this); | ||
}; | ||
@@ -125,3 +111,3 @@ | ||
*/ | ||
ServicePrototype.add = function add(object) { | ||
Service.prototype.add = function add(object) { | ||
/* istanbul ignore next */ | ||
@@ -135,3 +121,3 @@ if (this.get(object.name)) | ||
} | ||
return NamespacePrototype.add.call(this, object); | ||
return Namespace.prototype.add.call(this, object); | ||
}; | ||
@@ -142,3 +128,3 @@ | ||
*/ | ||
ServicePrototype.remove = function remove(object) { | ||
Service.prototype.remove = function remove(object) { | ||
if (object instanceof Method) { | ||
@@ -154,82 +140,22 @@ | ||
} | ||
return NamespacePrototype.remove.call(this, object); | ||
return Namespace.prototype.remove.call(this, object); | ||
}; | ||
/** | ||
* RPC implementation passed to {@link Service#create} performing a service request on network level, i.e. by utilizing http requests or websockets. | ||
* @typedef RPCImpl | ||
* @type {function} | ||
* @param {Method} method Reflected method being called | ||
* @param {Uint8Array} requestData Request data | ||
* @param {RPCCallback} callback Callback function | ||
* @returns {undefined} | ||
*/ | ||
/** | ||
* Node-style callback as used by {@link RPCImpl}. | ||
* @typedef RPCCallback | ||
* @type {function} | ||
* @param {?Error} error Error, if any, otherwise `null` | ||
* @param {Uint8Array} [responseData] Response data or `null` to signal end of stream, if there hasn't been an error | ||
* @returns {undefined} | ||
*/ | ||
/** | ||
* Creates a runtime service using the specified rpc implementation. | ||
* @param {function(Method, Uint8Array, function)} rpcImpl {@link RPCImpl|RPC implementation} | ||
* @param {RPCImpl} rpcImpl RPC implementation | ||
* @param {boolean} [requestDelimited=false] Whether requests are length-delimited | ||
* @param {boolean} [responseDelimited=false] Whether responses are length-delimited | ||
* @returns {rpc.Service} Runtime RPC service. Useful where requests and/or responses are streamed. | ||
* @returns {rpc.Service} RPC service. Useful where requests and/or responses are streamed. | ||
*/ | ||
ServicePrototype.create = function create(rpcImpl, requestDelimited, responseDelimited) { | ||
var rpcService = new rpc.Service(rpcImpl); | ||
this.methodsArray.forEach(function(method) { | ||
rpcService[util.lcFirst(method.name)] = function callVirtual(request, /* optional */ callback) { | ||
if (!rpcService.$rpc) { | ||
var err4 = Error("already ended"); | ||
if (callback) | ||
return callback(err4); | ||
throw err4; | ||
} | ||
if (!request) | ||
throw TypeError("request must not be null"); | ||
method.resolve(); | ||
var requestData = (requestDelimited ? method.resolvedRequestType.encodeDelimited(request) : method.resolvedRequestType.encode(request)).finish(); // never throws if request is true-ish | ||
// Calls the custom RPC implementation with the reflected method and binary request data | ||
// and expects the rpc implementation to call its callback with the binary response data. | ||
return rpcImpl(method, requestData, function(err, responseData) { | ||
if (err) { | ||
rpcService.emit("error", err, method); | ||
/* istanbul ignore else */ | ||
if (callback) | ||
return callback(err); | ||
/* istanbul ignore next */ | ||
throw err; | ||
} | ||
if (responseData === null) { | ||
rpcService.end(/* endedByRPC */ true); | ||
return undefined; | ||
} | ||
var response; | ||
try { | ||
response = responseDelimited ? method.resolvedResponseType.decodeDelimited(responseData) : method.resolvedResponseType.decode(responseData); | ||
} catch (err2) { | ||
rpcService.emit("error", err2, method); | ||
/* istanbul ignore else */ | ||
if (callback) | ||
return callback("error", err2); | ||
/* istanbul ignore next */ | ||
throw err2; | ||
} | ||
rpcService.emit("data", response, method); | ||
/* istanbul ignore else */ | ||
if (callback) | ||
return callback(null, response); | ||
/* istanbul ignore next */ | ||
return undefined; | ||
}); | ||
}; | ||
}); | ||
Service.prototype.create = function create(rpcImpl, requestDelimited, responseDelimited) { | ||
var rpcService = new rpc.Service(rpcImpl, requestDelimited, responseDelimited); | ||
for (var i = 0; i < /* initializes */ this.methodsArray.length; ++i) { | ||
rpcService[util.lcFirst(this._methodsArray[i].resolve().name)] = util.codegen("r","c")("return this.rpcCall(m,q,s,r,c)").eof(util.lcFirst(this._methodsArray[i].name), { | ||
m: this._methodsArray[i], | ||
q: this._methodsArray[i].resolvedRequestType.ctor, | ||
s: this._methodsArray[i].resolvedResponseType.ctor | ||
}); | ||
} | ||
return rpcService; | ||
}; |
@@ -116,8 +116,8 @@ "use strict"; | ||
commentLine = line; | ||
commentText = source | ||
var lines = source | ||
.substring(start, end) | ||
.split(/\n/g) | ||
.map(function(line) { | ||
return line.replace(/ *[*/]+ */, "").trim(); | ||
}) | ||
.split(/\n/g); | ||
for (var i = 0; i < lines.length; ++i) | ||
lines[i] = lines[i].replace(/^ *[*/]+ */, "").trim(); | ||
commentText = lines | ||
.join("\n") | ||
@@ -268,2 +268,2 @@ .trim(); | ||
/* eslint-enable callback-return */ | ||
} | ||
} |
120
src/type.js
@@ -6,12 +6,8 @@ "use strict"; | ||
var Namespace = require("./namespace"); | ||
/** @alias Namespace.prototype */ | ||
var NamespacePrototype = Namespace.prototype; | ||
/** @alias Type.prototype */ | ||
var TypePrototype = Namespace.extend(Type); | ||
((Type.prototype = Object.create(Namespace.prototype)).constructor = Type).className = "Type"; | ||
Type.className = "Type"; | ||
var Enum = require("./enum"), | ||
OneOf = require("./oneof"), | ||
Field = require("./field"), | ||
MapField = require("./mapfield"), | ||
Service = require("./service"), | ||
@@ -28,14 +24,3 @@ Class = require("./class"), | ||
var nestedTypes = [ Enum, Type, Field, Service ]; | ||
/** | ||
* Tests if the specified JSON object describes a message type. | ||
* @param {*} json JSON object to test | ||
* @returns {boolean} `true` if the object describes a message type | ||
*/ | ||
Type.testJSON = function testJSON(json) { | ||
return Boolean(json && json.fields); | ||
}; | ||
/** | ||
* Creates a type from JSON. | ||
@@ -50,21 +35,28 @@ * @param {string} name Message name | ||
type.reserved = json.reserved; | ||
Object.keys(json.fields).forEach(function(fieldName) { | ||
type.add(Field.fromJSON(fieldName, json.fields[fieldName])); | ||
}); | ||
var names = Object.keys(json.fields), | ||
i = 0; | ||
for (; i < names.length; ++i) | ||
type.add( | ||
( typeof json.fields[names[i]].keyType !== "undefined" | ||
? MapField.fromJSON | ||
: Field.fromJSON )(names[i], json.fields[names[i]]) | ||
); | ||
if (json.oneofs) | ||
Object.keys(json.oneofs).forEach(function(oneOfName) { | ||
type.add(OneOf.fromJSON(oneOfName, json.oneofs[oneOfName])); | ||
}); | ||
for (names = Object.keys(json.oneofs), i = 0; i < names.length; ++i) | ||
type.add(OneOf.fromJSON(names[i], json.oneofs[names[i]])); | ||
if (json.nested) | ||
Object.keys(json.nested).forEach(function(nestedName) { | ||
var nested = json.nested[nestedName]; | ||
for (var i = 0; i < nestedTypes.length; ++i) { | ||
if (nestedTypes[i].testJSON(nested)) { | ||
type.add(nestedTypes[i].fromJSON(nestedName, nested)); | ||
return; | ||
} | ||
} | ||
/* istanbul ignore next */ | ||
throw Error("invalid nested object in " + type + ": " + nestedName); | ||
}); | ||
for (names = Object.keys(json.nested), i = 0; i < names.length; ++i) { | ||
var nested = json.nested[names[i]]; | ||
type.add( // most to least likely | ||
( nested.id !== undefined | ||
? Field.fromJSON | ||
: nested.fields !== undefined | ||
? Type.fromJSON | ||
: nested.values !== undefined | ||
? Enum.fromJSON | ||
: nested.methods !== undefined | ||
? Service.fromJSON | ||
: Namespace.fromJSON )(names[i], nested) | ||
); | ||
} | ||
if (json.extensions && json.extensions.length) | ||
@@ -149,3 +141,3 @@ type.extensions = json.extensions; | ||
Object.defineProperties(TypePrototype, { | ||
Object.defineProperties(Type.prototype, { | ||
@@ -164,4 +156,3 @@ /** | ||
this._fieldsById = {}; | ||
var names = Object.keys(this.fields); | ||
for (var i = 0; i < names.length; ++i) { | ||
for (var names = Object.keys(this.fields), i = 0; i < names.length; ++i) { | ||
var field = this.fields[names[i]], | ||
@@ -211,3 +202,3 @@ id = field.id; | ||
get: function() { | ||
return this._ctor || (this._ctor = Class.create(this).constructor); | ||
return this._ctor || (this._ctor = Class(this).constructor); | ||
}, | ||
@@ -235,4 +226,4 @@ set: function(ctor) { | ||
*/ | ||
TypePrototype.toJSON = function toJSON() { | ||
var inherited = NamespacePrototype.toJSON.call(this); | ||
Type.prototype.toJSON = function toJSON() { | ||
var inherited = Namespace.prototype.toJSON.call(this); | ||
return { | ||
@@ -252,3 +243,3 @@ options : inherited && inherited.options || undefined, | ||
*/ | ||
TypePrototype.resolveAll = function resolveAll() { | ||
Type.prototype.resolveAll = function resolveAll() { | ||
var fields = this.fieldsArray, i = 0; | ||
@@ -260,3 +251,3 @@ while (i < fields.length) | ||
oneofs[i++].resolve(); | ||
return NamespacePrototype.resolve.call(this); | ||
return Namespace.prototype.resolve.call(this); | ||
}; | ||
@@ -267,4 +258,7 @@ | ||
*/ | ||
TypePrototype.get = function get(name) { | ||
return NamespacePrototype.get.call(this, name) || this.fields && this.fields[name] || this.oneofs && this.oneofs[name] || null; | ||
Type.prototype.get = function get(name) { | ||
return this.fields[name] | ||
|| this.oneofs && this.oneofs[name] | ||
|| this.nested && this.nested[name] | ||
|| null; | ||
}; | ||
@@ -279,6 +273,7 @@ | ||
*/ | ||
TypePrototype.add = function add(object) { | ||
/* istanbul ignore next */ | ||
Type.prototype.add = function add(object) { | ||
if (this.get(object.name)) | ||
throw Error("duplicate name '" + object.name + "' in " + this); | ||
if (object instanceof Field && object.extend === undefined) { | ||
@@ -288,5 +283,6 @@ // NOTE: Extension fields aren't actual fields on the declaring type, but nested objects. | ||
// type instead. | ||
/* istanbul ignore next */ | ||
if (this.fieldsById[object.id]) | ||
throw Error("duplicate id " + object.id + " in " + this); | ||
if (object.parent) | ||
@@ -306,3 +302,3 @@ object.parent.remove(object); | ||
} | ||
return NamespacePrototype.add.call(this, object); | ||
return Namespace.prototype.add.call(this, object); | ||
}; | ||
@@ -317,3 +313,3 @@ | ||
*/ | ||
TypePrototype.remove = function remove(object) { | ||
Type.prototype.remove = function remove(object) { | ||
if (object instanceof Field && object.extend === undefined) { | ||
@@ -338,3 +334,3 @@ // See Type#add for the reason why extension fields are excluded here. | ||
} | ||
return NamespacePrototype.remove.call(this, object); | ||
return Namespace.prototype.remove.call(this, object); | ||
}; | ||
@@ -347,3 +343,3 @@ | ||
*/ | ||
TypePrototype.create = function create(properties) { | ||
Type.prototype.create = function create(properties) { | ||
return new this.ctor(properties); | ||
@@ -356,7 +352,9 @@ }; | ||
*/ | ||
TypePrototype.setup = function setup() { | ||
Type.prototype.setup = function setup() { | ||
// Sets up everything at once so that the prototype chain does not have to be re-evaluated | ||
// multiple times (V8, soft-deopt prototype-check). | ||
var fullName = this.fullName, | ||
types = this.fieldsArray.map(function(fld) { return fld.resolve().resolvedType; }); | ||
types = []; | ||
for (var i = 0; i < /* initializes */ this.fieldsArray.length; ++i) | ||
types.push(this._fieldsArray[i].resolve().resolvedType); | ||
this.encode = encoder(this).eof(fullName + "$encode", { | ||
@@ -393,3 +391,3 @@ Writer : Writer, | ||
*/ | ||
TypePrototype.encode = function encode_setup(message, writer) { | ||
Type.prototype.encode = function encode_setup(message, writer) { | ||
return this.setup().encode(message, writer); // overrides this method | ||
@@ -404,3 +402,3 @@ }; | ||
*/ | ||
TypePrototype.encodeDelimited = function encodeDelimited(message, writer) { | ||
Type.prototype.encodeDelimited = function encodeDelimited(message, writer) { | ||
return this.encode(message, writer && writer.len ? writer.fork() : writer).ldelim(); | ||
@@ -415,3 +413,3 @@ }; | ||
*/ | ||
TypePrototype.decode = function decode_setup(reader, length) { | ||
Type.prototype.decode = function decode_setup(reader, length) { | ||
return this.setup().decode(reader, length); // overrides this method | ||
@@ -425,3 +423,3 @@ }; | ||
*/ | ||
TypePrototype.decodeDelimited = function decodeDelimited(reader) { | ||
Type.prototype.decodeDelimited = function decodeDelimited(reader) { | ||
if (!(reader instanceof Reader)) | ||
@@ -437,3 +435,3 @@ reader = Reader.create(reader); | ||
*/ | ||
TypePrototype.verify = function verify_setup(message) { | ||
Type.prototype.verify = function verify_setup(message) { | ||
return this.setup().verify(message); // overrides this method | ||
@@ -447,3 +445,3 @@ }; | ||
*/ | ||
TypePrototype.fromObject = function fromObject(object) { | ||
Type.prototype.fromObject = function fromObject(object) { | ||
return this.setup().fromObject(object); | ||
@@ -459,3 +457,3 @@ }; | ||
*/ | ||
TypePrototype.from = TypePrototype.fromObject; | ||
Type.prototype.from = Type.prototype.fromObject; | ||
@@ -486,4 +484,4 @@ /** | ||
*/ | ||
TypePrototype.toObject = function toObject(message, options) { | ||
Type.prototype.toObject = function toObject(message, options) { | ||
return this.setup().toObject(message, options); | ||
}; |
@@ -7,10 +7,7 @@ "use strict"; | ||
*/ | ||
var util = module.exports = require("./util/runtime"); | ||
var util = module.exports = require("./util/minimal"); | ||
util.asPromise = require("@protobufjs/aspromise"); | ||
util.codegen = require("@protobufjs/codegen"); | ||
util.EventEmitter = require("@protobufjs/eventemitter"); | ||
util.extend = require("@protobufjs/extend"); | ||
util.fetch = require("@protobufjs/fetch"); | ||
util.path = require("@protobufjs/path"); | ||
util.codegen = require("@protobufjs/codegen"); | ||
util.fetch = require("@protobufjs/fetch"); | ||
util.path = require("@protobufjs/path"); | ||
@@ -29,5 +26,7 @@ /** | ||
util.toArray = function toArray(object) { | ||
return object ? Object.keys(object).map(function(key) { | ||
return object[key]; | ||
}) : []; | ||
var array = []; | ||
if (object) | ||
for (var keys = Object.keys(object), i = 0; i < keys.length; ++i) | ||
array.push(object[keys[i]]); | ||
return array; | ||
}; | ||
@@ -45,11 +44,2 @@ | ||
/** | ||
* Converts the first character of a string to lower case. | ||
* @param {string} str String to convert | ||
* @returns {string} Converted string | ||
*/ | ||
util.lcFirst = function lcFirst(str) { | ||
return str.charAt(0).toLowerCase() + str.substring(1); | ||
}; | ||
/** | ||
* Converts the first character of a string to upper case. | ||
@@ -56,0 +46,0 @@ * @param {string} str String to convert |
"use strict"; | ||
module.exports = LongBits; | ||
var util = require("../util/runtime"); | ||
var util = require("../util/minimal"); | ||
@@ -40,5 +40,2 @@ /** | ||
/** @alias util.LongBits.prototype */ | ||
var LongBitsPrototype = LongBits.prototype; | ||
/** | ||
@@ -95,3 +92,3 @@ * Zero bits. | ||
return LongBits.fromNumber(value); | ||
if (typeof value === "string") { | ||
if (util.isString(value)) { | ||
/* istanbul ignore else */ | ||
@@ -111,3 +108,3 @@ if (util.Long) | ||
*/ | ||
LongBitsPrototype.toNumber = function toNumber(unsigned) { | ||
LongBits.prototype.toNumber = function toNumber(unsigned) { | ||
if (!unsigned && this.hi >>> 31) { | ||
@@ -128,3 +125,3 @@ var lo = ~this.lo + 1 >>> 0, | ||
*/ | ||
LongBitsPrototype.toLong = function toLong(unsigned) { | ||
LongBits.prototype.toLong = function toLong(unsigned) { | ||
return util.Long | ||
@@ -163,3 +160,3 @@ ? new util.Long(this.lo | 0, this.hi | 0, Boolean(unsigned)) | ||
*/ | ||
LongBitsPrototype.toHash = function toHash() { | ||
LongBits.prototype.toHash = function toHash() { | ||
return String.fromCharCode( | ||
@@ -181,3 +178,3 @@ this.lo & 255, | ||
*/ | ||
LongBitsPrototype.zzEncode = function zzEncode() { | ||
LongBits.prototype.zzEncode = function zzEncode() { | ||
var mask = this.hi >> 31; | ||
@@ -193,3 +190,3 @@ this.hi = ((this.hi << 1 | this.lo >>> 31) ^ mask) >>> 0; | ||
*/ | ||
LongBitsPrototype.zzDecode = function zzDecode() { | ||
LongBits.prototype.zzDecode = function zzDecode() { | ||
var mask = -(this.lo & 1); | ||
@@ -205,3 +202,3 @@ this.lo = ((this.lo >>> 1 | this.hi << 31) ^ mask) >>> 0; | ||
*/ | ||
LongBitsPrototype.length = function length() { | ||
LongBits.prototype.length = function length() { | ||
var part0 = this.lo, | ||
@@ -208,0 +205,0 @@ part1 = (this.lo >>> 28 | this.hi << 4) >>> 0, |
@@ -27,5 +27,4 @@ "use strict"; | ||
("return%j", invalid(field, "enum value")); | ||
var values = util.toArray(field.resolvedType.values); | ||
for (var j = 0; j < values.length; ++j) gen | ||
("case %d:", values[j]); | ||
for (var keys = Object.keys(field.resolvedType.values), j = 0; j < keys.length; ++j) gen | ||
("case %d:", field.resolvedType.values[keys[j]]); | ||
gen | ||
@@ -122,9 +121,9 @@ ("break") | ||
/* eslint-disable no-unexpected-multiline */ | ||
var fields = mtype.fieldsArray; | ||
if (!fields.length) | ||
if (/* initializes */ !mtype.fieldsArray.length) | ||
return util.codegen()("return null"); | ||
var gen = util.codegen("m"); | ||
for (var i = 0; i < fields.length; ++i) { | ||
var field = fields[i].resolve(), | ||
for (var i = 0; i < mtype._fieldsArray.length; ++i) { | ||
var field = mtype._fieldsArray[i].resolve(), | ||
ref = "m" + util.safeProp(field.name); | ||
@@ -131,0 +130,0 @@ |
@@ -6,7 +6,5 @@ "use strict"; | ||
var Writer = require("./writer"); | ||
/** @alias BufferWriter.prototype */ | ||
var BufferWriterPrototype = BufferWriter.prototype = Object.create(Writer.prototype); | ||
BufferWriterPrototype.constructor = BufferWriter; | ||
(BufferWriter.prototype = Object.create(Writer.prototype)).constructor = BufferWriter; | ||
var util = require("./util/runtime"); | ||
var util = require("./util/minimal"); | ||
@@ -50,4 +48,4 @@ var Buffer = util.Buffer; | ||
*/ | ||
BufferWriterPrototype.bytes = function write_bytes_buffer(value) { | ||
if (typeof value === "string") | ||
BufferWriter.prototype.bytes = function write_bytes_buffer(value) { | ||
if (util.isString(value)) | ||
value = Buffer.from(value, "base64"); // polyfilled | ||
@@ -71,3 +69,3 @@ var len = value.length >>> 0; | ||
*/ | ||
BufferWriterPrototype.string = function write_string_buffer(value) { | ||
BufferWriter.prototype.string = function write_string_buffer(value) { | ||
var len = Buffer.byteLength(value); | ||
@@ -74,0 +72,0 @@ this.uint32(len); |
"use strict"; | ||
module.exports = Writer; | ||
var util = require("./util/runtime"); | ||
var util = require("./util/minimal"); | ||
@@ -132,5 +132,2 @@ var BufferWriter; // cyclic | ||
? function create_buffer_setup() { | ||
/* istanbul ignore next */ | ||
if (!BufferWriter) | ||
BufferWriter = require("./writer_buffer"); | ||
return (Writer.create = function create_buffer() { | ||
@@ -159,5 +156,2 @@ return new BufferWriter(); | ||
/** @alias Writer.prototype */ | ||
var WriterPrototype = Writer.prototype; | ||
/** | ||
@@ -170,3 +164,3 @@ * Pushes a new operation to the queue. | ||
*/ | ||
WriterPrototype.push = function push(fn, len, val) { | ||
Writer.prototype.push = function push(fn, len, val) { | ||
this.tail = this.tail.next = new Op(fn, len, val); | ||
@@ -212,3 +206,3 @@ this.len += len; | ||
*/ | ||
WriterPrototype.uint32 = function write_uint32(value) { | ||
Writer.prototype.uint32 = function write_uint32(value) { | ||
// here, the call to this.push has been inlined and a varint specific Op subclass is used. | ||
@@ -233,3 +227,3 @@ // uint32 is by far the most frequently used operation and benefits significantly from this. | ||
*/ | ||
WriterPrototype.int32 = function write_int32(value) { | ||
Writer.prototype.int32 = function write_int32(value) { | ||
return value < 0 | ||
@@ -245,3 +239,3 @@ ? this.push(writeVarint64, 10, LongBits.fromNumber(value)) // 10 bytes per spec | ||
*/ | ||
WriterPrototype.sint32 = function write_sint32(value) { | ||
Writer.prototype.sint32 = function write_sint32(value) { | ||
return this.uint32((value << 1 ^ value >> 31) >>> 0); | ||
@@ -269,3 +263,3 @@ }; | ||
*/ | ||
WriterPrototype.uint64 = function write_uint64(value) { | ||
Writer.prototype.uint64 = function write_uint64(value) { | ||
var bits = LongBits.from(value); | ||
@@ -282,3 +276,3 @@ return this.push(writeVarint64, bits.length(), bits); | ||
*/ | ||
WriterPrototype.int64 = WriterPrototype.uint64; | ||
Writer.prototype.int64 = Writer.prototype.uint64; | ||
@@ -291,3 +285,3 @@ /** | ||
*/ | ||
WriterPrototype.sint64 = function write_sint64(value) { | ||
Writer.prototype.sint64 = function write_sint64(value) { | ||
var bits = LongBits.from(value).zzEncode(); | ||
@@ -302,3 +296,3 @@ return this.push(writeVarint64, bits.length(), bits); | ||
*/ | ||
WriterPrototype.bool = function write_bool(value) { | ||
Writer.prototype.bool = function write_bool(value) { | ||
return this.push(writeByte, 1, value ? 1 : 0); | ||
@@ -319,3 +313,3 @@ }; | ||
*/ | ||
WriterPrototype.fixed32 = function write_fixed32(value) { | ||
Writer.prototype.fixed32 = function write_fixed32(value) { | ||
return this.push(writeFixed32, 4, value >>> 0); | ||
@@ -329,3 +323,3 @@ }; | ||
*/ | ||
WriterPrototype.sfixed32 = function write_sfixed32(value) { | ||
Writer.prototype.sfixed32 = function write_sfixed32(value) { | ||
return this.push(writeFixed32, 4, value << 1 ^ value >> 31); | ||
@@ -340,3 +334,3 @@ }; | ||
*/ | ||
WriterPrototype.fixed64 = function write_fixed64(value) { | ||
Writer.prototype.fixed64 = function write_fixed64(value) { | ||
var bits = LongBits.from(value); | ||
@@ -352,3 +346,3 @@ return this.push(writeFixed32, 4, bits.lo).push(writeFixed32, 4, bits.hi); | ||
*/ | ||
WriterPrototype.sfixed64 = function write_sfixed64(value) { | ||
Writer.prototype.sfixed64 = function write_sfixed64(value) { | ||
var bits = LongBits.from(value).zzEncode(); | ||
@@ -406,3 +400,3 @@ return this.push(writeFixed32, 4, bits.lo).push(writeFixed32, 4, bits.hi); | ||
*/ | ||
WriterPrototype.float = function write_float(value) { | ||
Writer.prototype.float = function write_float(value) { | ||
return this.push(writeFloat, 4, value); | ||
@@ -478,3 +472,3 @@ }; | ||
*/ | ||
WriterPrototype.double = function write_double(value) { | ||
Writer.prototype.double = function write_double(value) { | ||
return this.push(writeDouble, 8, value); | ||
@@ -498,7 +492,7 @@ }; | ||
*/ | ||
WriterPrototype.bytes = function write_bytes(value) { | ||
Writer.prototype.bytes = function write_bytes(value) { | ||
var len = value.length >>> 0; | ||
if (!len) | ||
return this.push(writeByte, 1, 0); | ||
if (typeof value === "string") { | ||
if (util.isString(value)) { | ||
var buf = Writer.alloc(len = base64.length(value)); | ||
@@ -516,3 +510,3 @@ base64.decode(value, buf, 0); | ||
*/ | ||
WriterPrototype.string = function write_string(value) { | ||
Writer.prototype.string = function write_string(value) { | ||
var len = utf8.length(value); | ||
@@ -529,3 +523,3 @@ return len | ||
*/ | ||
WriterPrototype.fork = function fork() { | ||
Writer.prototype.fork = function fork() { | ||
this.states = new State(this); | ||
@@ -541,3 +535,3 @@ this.head = this.tail = new Op(noop, 0, 0); | ||
*/ | ||
WriterPrototype.reset = function reset() { | ||
Writer.prototype.reset = function reset() { | ||
if (this.states) { | ||
@@ -559,3 +553,3 @@ this.head = this.states.head; | ||
*/ | ||
WriterPrototype.ldelim = function ldelim() { | ||
Writer.prototype.ldelim = function ldelim() { | ||
var head = this.head, | ||
@@ -577,3 +571,3 @@ tail = this.tail, | ||
*/ | ||
WriterPrototype.finish = function finish() { | ||
Writer.prototype.finish = function finish() { | ||
var head = this.head.next, // skip noop | ||
@@ -590,1 +584,5 @@ buf = this.constructor.alloc(this.len), | ||
}; | ||
Writer._configure = function(BufferWriter_) { | ||
BufferWriter = BufferWriter_; | ||
}; |
@@ -12,5 +12,3 @@ var tape = require("tape"); | ||
test.throws(function() { | ||
new protobuf.Class("a"); | ||
}, TypeError, "new Class should throw if first argument is not a Type"); | ||
test.equal(protobuf.Class.create, protobuf.Class, "Class.create should be an alias of Class (constructor)"); | ||
@@ -17,0 +15,0 @@ test.throws(function() { |
@@ -152,2 +152,3 @@ var tape = require("tape"); | ||
test.same(Message.ctor.fromObject(obj), msg, "should convert the same using the static and the instance method"); | ||
test.equal(Message.fromObject(msg), msg, "should just return the object if already a runtime message"); | ||
@@ -154,0 +155,0 @@ var buf = protobuf.util.newBuffer(3); |
@@ -12,2 +12,6 @@ var tape = require("tape"); | ||
test.throws(function() { | ||
new protobuf.Enum("Test", true); | ||
}, TypeError, "should throw if values is specified but not an object"); | ||
test.same(enm.valuesById, { | ||
@@ -18,2 +22,18 @@ 1: "a", | ||
test.throws(function() { | ||
enm.add(2, 2); | ||
}, TypeError, "should throw if name is not a string"); | ||
test.throws(function() { | ||
enm.add("c", 1.5); | ||
}, TypeError, "should throw if id is not an integer"); | ||
test.throws(function() { | ||
enm.add("b", 2); | ||
}, Error, "should throw if name is a duplicate"); | ||
test.throws(function() { | ||
enm.add("c", 2); | ||
}, Error, "should throw if id is a duplicate"); | ||
enm.add("c", 3); | ||
@@ -31,2 +51,10 @@ test.same(enm.values, { | ||
test.throws(function() { | ||
enm.remove(1); | ||
}, TypeError, "should throw if name is not a string"); | ||
test.throws(function() { | ||
enm.remove("d"); | ||
}, Error, "should throw if name is not present"); | ||
enm.remove("b"); | ||
@@ -33,0 +61,0 @@ test.same(enm.values, { |
@@ -6,2 +6,37 @@ var tape = require("tape"); | ||
tape.test("reflected fields", function(test) { | ||
test.throws(function() { | ||
new protobuf.Field(1); | ||
}, TypeError, "should throw if name is not a string"); | ||
test.throws(function() { | ||
new protobuf.Field("a", 1.5); | ||
}, TypeError, "should throw if id is not an integer"); | ||
test.throws(function() { | ||
new protobuf.Field("a", -5); | ||
}, TypeError, "should throw if id is negative"); | ||
test.throws(function() { | ||
new protobuf.Field("a", 1, 5); | ||
}, TypeError, "should throw if type is not a string"); | ||
test.throws(function() { | ||
new protobuf.Field("a", 1, "uint32", "optiona"); | ||
}, TypeError, "should throw if rule is specified but not a rule string"); | ||
test.throws(function() { | ||
new protobuf.Field("a", 1, "uint32", "optional", 1); | ||
}, TypeError, "should throw if extend is specified but not a string"); | ||
test.throws(function() { | ||
new protobuf.Field("a", 1, "uint32", "optional", "B", true); | ||
}, TypeError, "should throw if options is specified but not an object"); | ||
test.throws(function() { | ||
var field = new protobuf.Field("a", 1, "UnDeFiNeD"); | ||
new protobuf.Root().add(new protobuf.Type("A").add(field)); | ||
field.resolve(); | ||
}, Error, "should throw if type cannot be resolved"); | ||
var root = new protobuf.Root(), | ||
@@ -19,4 +54,3 @@ type, | ||
root | ||
.add( | ||
root.add( | ||
type = new protobuf.Type("Test").add( | ||
@@ -27,6 +61,6 @@ field = new protobuf.Field("a", 1, "Enm", /* skipped rule and extend, */ { "default": "ONE" }) | ||
new protobuf.Enum("Enm", { "ONE": 1, "TWO": 2 }) | ||
) | ||
.resolveAll(); | ||
).resolveAll(); | ||
test.ok(field.resolvedType instanceof protobuf.Enum, "should resolve to an enum"); | ||
test.equal(field.typeDefault, 1, "should recognize enum default values as strings"); | ||
@@ -37,2 +71,3 @@ | ||
field.resolve(); | ||
test.equal(field.typeDefault, 2, "should recognize enum default values as numbers"); | ||
@@ -48,5 +83,10 @@ | ||
field.resolve(); | ||
test.same(Array.prototype.slice.call(field.typeDefault), "teststr".split("").map(function(c) { return c.charCodeAt(0); }), "should recognize bytes default values as strings"); | ||
field.resolved = 2; | ||
field.resolve(); | ||
test.equal(field.resolved, 2, "should not resolve again if already resolved"); | ||
test.end(); | ||
}); |
@@ -15,4 +15,2 @@ var tape = require("tape"); | ||
test.ok(protobuf.MapField.testJSON(def), "should recognize a mapfield definition as JSON"); | ||
var field = protobuf.MapField.fromJSON("a", def); | ||
@@ -19,0 +17,0 @@ test.same(field.toJSON(), def, "should construct from and convert back to JSON"); |
@@ -19,3 +19,2 @@ var tape = require("tape"); | ||
tape.test("reflected namespaces", function(test) { | ||
test.ok(protobuf.Namespace.testJSON(def), "should recognize namespaces as JSON"); | ||
@@ -27,15 +26,18 @@ var ns = protobuf.Namespace.fromJSON("ns", def); | ||
ns = root.lookup("ns").resolveAll(); | ||
test.same(ns.getEnum("Enm"), { ONE: 1, TWO: 2 }, "should get enums"); | ||
test.same(ns.getEnum("Enm"), { ONE: 1, TWO: 2 }, "should get enums"); | ||
test.throws(function() { | ||
ns.getEnum("Msg"); | ||
}, Error, "should throw when getting a message as an enum") | ||
}, Error, "should throw when getting a message as an enum"); | ||
test.throws(function() { | ||
ns.getEnum("NOTFOUND"); | ||
}, Error, "should throw when getting null as an enum") | ||
}, Error, "should throw when getting null as an enum"); | ||
test.ok(ns.lookupType("Msg"), "should lookup types"); | ||
test.throws(function() { | ||
ns.lookupType("Enm"); | ||
}, Error, "should throw when looking up an enum as a type"); | ||
test.throws(function() { | ||
@@ -46,5 +48,7 @@ ns.lookupType("NOTFOUND"); | ||
test.ok(ns.lookupEnum("Enm"), "should lookup enums"); | ||
test.throws(function() { | ||
ns.lookupEnum("Msg"); | ||
}, Error, "should throw when looking up a type as an enum"); | ||
test.throws(function() { | ||
@@ -55,5 +59,7 @@ ns.lookupEnum("NOTFOUND"); | ||
test.ok(ns.lookupService("Svc"), "should lookup services"); | ||
test.throws(function() { | ||
ns.lookupService("Msg"); | ||
}, Error, "should throw when looking up a type as a service"); | ||
test.throws(function() { | ||
@@ -64,18 +70,69 @@ ns.lookupService("NOTFOUND"); | ||
test.equal(ns.lookup(""), ns, "should lookup itself for an empty path"); | ||
test.equal(ns.lookup([]), ns, "should lookup itself for []"); | ||
test.ok(ns.lookup(".") instanceof protobuf.Root, "should lookup root for ."); | ||
test.ok(ns.lookup([""]) instanceof protobuf.Root, "should lookup root for [\"\"]"); | ||
test.throws(function() { | ||
ns.define(null); | ||
}, "should throw when path is not a string or array"); | ||
test.throws(function() { | ||
ns.define(".sub", {}); | ||
}, "should throw when defining absolute .sub"); | ||
test.throws(function() { | ||
ns.define(["", "sub"], {}); | ||
}, "should throw when defining absolute [\"\", \"sub\"]"); | ||
var sub = ns.define("sub", {}); | ||
test.equal(ns.lookup("sub"), sub, "should define sub namespaces"); | ||
test.throws(function() { | ||
ns.add(new protobuf.ReflectionObject("invalid")); | ||
}, TypeError, "should throw when adding invalid nested objects"); | ||
test.throws(function() { | ||
ns.add(new protobuf.Enum("sub")); | ||
}, Error, "should throw on duplicate names"); | ||
sub = ns.define("sub.sub"); | ||
test.equal(ns.lookup("sub.sub"), sub, "should define sub sub namespaces"); | ||
test.throws(function() { | ||
ns.remove(true); | ||
}, TypeError, "should throw when trying to remove non-reflection objects"); | ||
test.throws(function() { | ||
ns.remove(new protobuf.Enum("Enm")); | ||
}, Error, "should throw when trying to remove non-children"); | ||
test.throws(function() { | ||
ns.add(new protobuf.Enum("MyEnum", {})); | ||
ns.define("MyEnum"); | ||
}, Error, "should throw when trying to define a path conflicting with non-namespace objects"); | ||
ns = protobuf.Namespace.fromJSON("My", { | ||
nested: { | ||
Message: { fields: {} }, | ||
Enum: { values: {} }, | ||
Service: { methods: {} }, | ||
extensionField: { type: "string", id: 1000, extend: "Message" }, | ||
Other: { nested: {} } | ||
} | ||
}); | ||
test.same(ns.toJSON(), { | ||
nested: { | ||
Message: { extensions: undefined, fields: {}, group: undefined, nested: undefined, oneofs: undefined, options: undefined, reserved: undefined }, | ||
Enum: { options: undefined, values: {} }, | ||
Service: { methods: {}, nested: undefined, options: undefined }, | ||
extensionField: { extend: "Message", id: 1000, options: undefined, rule: undefined, type: "string" }, | ||
Other: { nested: undefined, options: undefined } | ||
}, | ||
options: undefined | ||
}, "should create from Type, Enum, Service, extension Field and Namespace JSON"); | ||
test.end(); | ||
}); |
@@ -21,4 +21,2 @@ var tape = require("tape"); | ||
test.ok(protobuf.OneOf.testJSON(def), "should recognize a oneof definition as JSON"); | ||
var oneof = protobuf.OneOf.fromJSON("kind", { | ||
@@ -25,0 +23,0 @@ oneof: ["a", "b"], |
@@ -9,3 +9,3 @@ var tape = require("tape"); | ||
nested: {}, | ||
options: undefined | ||
options: { javaPackage: "com.something" } | ||
}; | ||
@@ -15,4 +15,2 @@ | ||
test.equal(Root.testJSON, protobuf.Namespace.testJSON, "should inherit testJSON via NamespaceBase"); | ||
var root = Root.fromJSON(def); | ||
@@ -19,0 +17,0 @@ test.ok(root instanceof Root, "should construct from JSON"); |
@@ -78,8 +78,20 @@ var tape = require("tape"); | ||
test.throws(function() { | ||
service.myMethod(MyRequest.create({ path: "/" })); | ||
}, Error, "should throw if already ended"); | ||
var count = 0, | ||
total = 1; | ||
if (typeof Promise !== "undefined") { | ||
++total; | ||
var promise = service.myMethod(MyRequest.create({ path: "/" })); | ||
promise.catch(function(err) { | ||
test.ok(err, "should return an error if already ended (Promise)"); | ||
if (++count === total) | ||
test.end(); | ||
}); | ||
test.ok(promise instanceof Promise, "should return a promise if callback has been omitted (even if already ended)"); | ||
} | ||
service.myMethod(MyRequest.create({ path: "/" }), function(err) { | ||
test.ok(err, "should return an error if already ended"); | ||
test.end(); | ||
if (++count === total) | ||
test.end(); | ||
}); | ||
@@ -86,0 +98,0 @@ }); |
@@ -28,2 +28,6 @@ var tape = require("tape"); | ||
test.throws(function() { | ||
MyService.create(); | ||
}, TypeError, "should throw if rpcImpl is not specified"); | ||
function rpcImpl(method, requestData, callback) { | ||
@@ -46,3 +50,3 @@ if (requestData) { | ||
service.doSomething(); | ||
}, TypeError, "should throw if request is false-ish"); | ||
}, TypeError, "should throw if request is not specified"); | ||
@@ -66,2 +70,19 @@ test.test(test.name + " - should propagate errors from rpcImpl", function(test) { | ||
test.test(test.name + " - should catch errors within rpcImpl", function(test) { | ||
var err = Error(); | ||
var service2 = MyService.create(function(method, requestData, callback) { throw err; }); | ||
test.plan(2); | ||
var count = 0; | ||
service2.on("error", function(err2) { | ||
test.equal(err2, err, "should emit the exact error"); | ||
if (++count === 2) | ||
test.end(); | ||
}); | ||
service2.doSomething({}, function(err2) { | ||
test.equal(err2, err, "should return the exact error"); | ||
if (++count === 2) | ||
test.end(); | ||
}); | ||
}); | ||
test.test(test.name + " - should return errors from decoding", function(test) { | ||
@@ -68,0 +89,0 @@ var service2 = MyService.create(function(method, requestData, callback) { callback(null, protobuf.util.newBuffer(0) ); }, true, true); |
@@ -22,5 +22,2 @@ var tape = require("tape"); | ||
test.equal(protobuf.Service.testJSON(def), true, "should recognize services as JSON"); | ||
test.equal(protobuf.Method.testJSON(methodDef), true, "should recognize methods as JSON"); | ||
var MyService = protobuf.Service.fromJSON("MyService", def); | ||
@@ -27,0 +24,0 @@ test.same(MyService.toJSON(), def, "should construct without methods from and convert back to JSON"); |
@@ -44,3 +44,2 @@ var tape = require("tape"); | ||
test.ok(protobuf.Type.testJSON(def), "should recognize types as JSON"); | ||
var type = protobuf.Type.fromJSON("Test", def); | ||
@@ -63,3 +62,44 @@ test.same(type.toJSON(), def, "should construct from and convert back to JSON"); | ||
type = protobuf.Type.fromJSON("My", { | ||
fields: { | ||
a: { | ||
type: "string", | ||
id: 1 | ||
} | ||
}, | ||
nested: { | ||
Type: { fields: {} }, | ||
Enum: { values: {} }, | ||
Service: { methods: {} }, | ||
extensionField: { type: "string", id: 1000, extend: "Message" }, | ||
Other: { nested: {} } | ||
} | ||
}); | ||
test.same(type.toJSON(), { | ||
fields: { | ||
a: { extend: undefined, id: 1, options: undefined, rule: undefined, type: "string" } | ||
}, | ||
oneofs: undefined, | ||
extensions: undefined, | ||
reserved: undefined, | ||
group: undefined, | ||
nested: { | ||
Type: { extensions: undefined, fields: {}, group: undefined, nested: undefined, oneofs: undefined, options: undefined, reserved: undefined }, | ||
Enum: { options: undefined, values: {} }, | ||
Service: { methods: {}, nested: undefined, options: undefined }, | ||
extensionField: { extend: "Message", id: 1000, options: undefined, rule: undefined, type: "string" }, | ||
Other: { nested: undefined, options: undefined } | ||
}, | ||
options: undefined | ||
}, "should create from Field, Type, Enum, Service, extension Field and Namespace JSON"); | ||
test.throws(function() { | ||
type.add(new protobuf.Enum("Enum")); | ||
}, Error, "should throw when trying to add duplicate names"); | ||
test.throws(function() { | ||
type.add(new protobuf.Field("c", 1, "uint32")); | ||
}, Error, "should throw when trying to add duplicate ids"); | ||
test.end(); | ||
}); |
@@ -16,2 +16,3 @@ var tape = require("tape"); | ||
string value = 1 [(my_options) = { a: \"foo\" b: \"bar\" }];\ | ||
string value2 = 2 [(my_options) = { a: \"foo\" b { c: \"bar\" } }];\ | ||
}"; | ||
@@ -23,3 +24,4 @@ | ||
test.same(Test.fields.value.options, { "(my_options).a": "foo", "(my_options).b": "bar" }, "should parse correctly"); | ||
test.same(Test.fields.value2.options, { "(my_options).a": "foo", "(my_options).b.c": "bar" }, "should parse correctly when nested"); | ||
test.end(); | ||
}); |
/*eslint-disable block-scoped-var, no-redeclare, no-control-regex, no-prototype-builtins*/ | ||
"use strict"; | ||
var $protobuf = require("../../runtime"); | ||
var $protobuf = require("../../minimal"); | ||
@@ -15,3 +15,3 @@ // Common aliases | ||
// Exported root namespace | ||
var $root = {}; | ||
var $root = $protobuf.roots.test_comments || ($protobuf.roots.test_comments = {}); | ||
@@ -31,7 +31,5 @@ $root.Test1 = (function() { | ||
function Test1(properties) { | ||
if (properties) { | ||
var keys = Object.keys(properties); | ||
for (var i = 0; i < keys.length; ++i) | ||
if (properties) | ||
for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) | ||
this[keys[i]] = properties[keys[i]]; | ||
} | ||
} | ||
@@ -52,3 +50,3 @@ | ||
/** | ||
* Field with a comment. | ||
* Field with a comment and a <a href="http://example.com/foo/">link</a> | ||
* @type {boolean} | ||
@@ -175,2 +173,3 @@ */ | ||
* This is an alias of {@link Test1.fromObject}. | ||
* @function | ||
* @param {Object.<string,*>} object Plain object | ||
@@ -234,7 +233,5 @@ * @returns {Test1} Test1 | ||
function Test2(properties) { | ||
if (properties) { | ||
var keys = Object.keys(properties); | ||
for (var i = 0; i < keys.length; ++i) | ||
if (properties) | ||
for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) | ||
this[keys[i]] = properties[keys[i]]; | ||
} | ||
} | ||
@@ -328,2 +325,3 @@ | ||
* This is an alias of {@link Test2.fromObject}. | ||
* @function | ||
* @param {Object.<string,*>} object Plain object | ||
@@ -384,2 +382,2 @@ * @returns {Test2} Test2 | ||
module.exports = $protobuf.roots["test_comments"] = $root; | ||
module.exports = $root; |
/*eslint-disable block-scoped-var, no-redeclare, no-control-regex, no-prototype-builtins*/ | ||
"use strict"; | ||
var $protobuf = require("../../runtime"); | ||
var $protobuf = require("../../minimal"); | ||
@@ -15,3 +15,3 @@ // Common aliases | ||
// Exported root namespace | ||
var $root = {}; | ||
var $root = $protobuf.roots.test_convert || ($protobuf.roots.test_convert = {}); | ||
@@ -27,7 +27,5 @@ $root.Message = (function() { | ||
function Message(properties) { | ||
if (properties) { | ||
var keys = Object.keys(properties); | ||
for (var i = 0; i < keys.length; ++i) | ||
if (properties) | ||
for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) | ||
this[keys[i]] = properties[keys[i]]; | ||
} | ||
} | ||
@@ -316,2 +314,4 @@ | ||
if (object.stringRepeated) { | ||
if (!Array.isArray(object.stringRepeated)) | ||
throw TypeError(".Message.stringRepeated: array expected"); | ||
message.stringRepeated = []; | ||
@@ -331,2 +331,4 @@ for (var i = 0; i < object.stringRepeated.length; ++i) | ||
if (object.uint64Repeated) { | ||
if (!Array.isArray(object.uint64Repeated)) | ||
throw TypeError(".Message.uint64Repeated: array expected"); | ||
message.uint64Repeated = []; | ||
@@ -346,5 +348,7 @@ for (var i = 0; i < object.uint64Repeated.length; ++i) | ||
$util.base64.decode(object.bytesVal, message.bytesVal = $util.newBuffer($util.base64.length(object.bytesVal)), 0); | ||
else if (object.bytesVal && object.bytesVal.length) | ||
else if (object.bytesVal.length) | ||
message.bytesVal = object.bytesVal; | ||
if (object.bytesRepeated) { | ||
if (!Array.isArray(object.bytesRepeated)) | ||
throw TypeError(".Message.bytesRepeated: array expected"); | ||
message.bytesRepeated = []; | ||
@@ -354,3 +358,3 @@ for (var i = 0; i < object.bytesRepeated.length; ++i) | ||
$util.base64.decode(object.bytesRepeated[i], message.bytesRepeated[i] = $util.newBuffer($util.base64.length(object.bytesRepeated[i])), 0); | ||
else if (object.bytesRepeated[i] && object.bytesRepeated[i].length) | ||
else if (object.bytesRepeated[i].length) | ||
message.bytesRepeated[i] = object.bytesRepeated[i]; | ||
@@ -369,2 +373,4 @@ } | ||
if (object.enumRepeated) { | ||
if (!Array.isArray(object.enumRepeated)) | ||
throw TypeError(".Message.enumRepeated: array expected"); | ||
message.enumRepeated = []; | ||
@@ -385,2 +391,4 @@ for (var i = 0; i < object.enumRepeated.length; ++i) | ||
if (object.int64Map) { | ||
if (typeof object.int64Map !== "object") | ||
throw TypeError(".Message.int64Map: object expected"); | ||
message.int64Map = {}; | ||
@@ -403,2 +411,3 @@ for (var keys = Object.keys(object.int64Map), i = 0; i < keys.length; ++i) | ||
* This is an alias of {@link Message.fromObject}. | ||
* @function | ||
* @param {Object.<string,*>} object Plain object | ||
@@ -521,2 +530,2 @@ * @returns {Message} Message | ||
module.exports = $protobuf.roots["test_convert"] = $root; | ||
module.exports = $root; |
/*eslint-disable block-scoped-var, no-redeclare, no-control-regex, no-prototype-builtins*/ | ||
"use strict"; | ||
var $protobuf = require("../../../runtime"); | ||
var $protobuf = require("../../../minimal"); | ||
@@ -15,3 +15,3 @@ // Common aliases | ||
// Exported root namespace | ||
var $root = {}; | ||
var $root = $protobuf.roots.test_vector_tile || ($protobuf.roots.test_vector_tile = {}); | ||
@@ -36,7 +36,5 @@ $root.vector_tile = (function() { | ||
function Tile(properties) { | ||
if (properties) { | ||
var keys = Object.keys(properties); | ||
for (var i = 0; i < keys.length; ++i) | ||
if (properties) | ||
for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) | ||
this[keys[i]] = properties[keys[i]]; | ||
} | ||
} | ||
@@ -154,5 +152,10 @@ | ||
if (object.layers) { | ||
if (!Array.isArray(object.layers)) | ||
throw TypeError(".vector_tile.Tile.layers: array expected"); | ||
message.layers = []; | ||
for (var i = 0; i < object.layers.length; ++i) | ||
for (var i = 0; i < object.layers.length; ++i) { | ||
if (typeof object.layers[i] !== "object") | ||
throw TypeError(".vector_tile.Tile.layers: object expected"); | ||
message.layers[i] = $types[0].fromObject(object.layers[i]); | ||
} | ||
} | ||
@@ -165,2 +168,3 @@ return message; | ||
* This is an alias of {@link vector_tile.Tile.fromObject}. | ||
* @function | ||
* @param {Object.<string,*>} object Plain object | ||
@@ -237,7 +241,5 @@ * @returns {vector_tile.Tile} Tile | ||
function Value(properties) { | ||
if (properties) { | ||
var keys = Object.keys(properties); | ||
for (var i = 0; i < keys.length; ++i) | ||
if (properties) | ||
for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) | ||
this[keys[i]] = properties[keys[i]]; | ||
} | ||
} | ||
@@ -465,2 +467,3 @@ | ||
* This is an alias of {@link vector_tile.Tile.Value.fromObject}. | ||
* @function | ||
* @param {Object.<string,*>} object Plain object | ||
@@ -557,7 +560,5 @@ * @returns {vector_tile.Tile.Value} Value | ||
function Feature(properties) { | ||
if (properties) { | ||
var keys = Object.keys(properties); | ||
for (var i = 0; i < keys.length; ++i) | ||
if (properties) | ||
for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) | ||
this[keys[i]] = properties[keys[i]]; | ||
} | ||
} | ||
@@ -754,2 +755,4 @@ | ||
if (object.tags) { | ||
if (!Array.isArray(object.tags)) | ||
throw TypeError(".vector_tile.Tile.Feature.tags: array expected"); | ||
message.tags = []; | ||
@@ -778,2 +781,4 @@ for (var i = 0; i < object.tags.length; ++i) | ||
if (object.geometry) { | ||
if (!Array.isArray(object.geometry)) | ||
throw TypeError(".vector_tile.Tile.Feature.geometry: array expected"); | ||
message.geometry = []; | ||
@@ -789,2 +794,3 @@ for (var i = 0; i < object.geometry.length; ++i) | ||
* This is an alias of {@link vector_tile.Tile.Feature.fromObject}. | ||
* @function | ||
* @param {Object.<string,*>} object Plain object | ||
@@ -866,7 +872,5 @@ * @returns {vector_tile.Tile.Feature} Feature | ||
function Layer(properties) { | ||
if (properties) { | ||
var keys = Object.keys(properties); | ||
for (var i = 0; i < keys.length; ++i) | ||
if (properties) | ||
for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) | ||
this[keys[i]] = properties[keys[i]]; | ||
} | ||
} | ||
@@ -1071,7 +1075,14 @@ | ||
if (object.features) { | ||
if (!Array.isArray(object.features)) | ||
throw TypeError(".vector_tile.Tile.Layer.features: array expected"); | ||
message.features = []; | ||
for (var i = 0; i < object.features.length; ++i) | ||
for (var i = 0; i < object.features.length; ++i) { | ||
if (typeof object.features[i] !== "object") | ||
throw TypeError(".vector_tile.Tile.Layer.features: object expected"); | ||
message.features[i] = $types[2].fromObject(object.features[i]); | ||
} | ||
} | ||
if (object.keys) { | ||
if (!Array.isArray(object.keys)) | ||
throw TypeError(".vector_tile.Tile.Layer.keys: array expected"); | ||
message.keys = []; | ||
@@ -1082,5 +1093,10 @@ for (var i = 0; i < object.keys.length; ++i) | ||
if (object.values) { | ||
if (!Array.isArray(object.values)) | ||
throw TypeError(".vector_tile.Tile.Layer.values: array expected"); | ||
message.values = []; | ||
for (var i = 0; i < object.values.length; ++i) | ||
for (var i = 0; i < object.values.length; ++i) { | ||
if (typeof object.values[i] !== "object") | ||
throw TypeError(".vector_tile.Tile.Layer.values: object expected"); | ||
message.values[i] = $types[4].fromObject(object.values[i]); | ||
} | ||
} | ||
@@ -1095,2 +1111,3 @@ if (object.extent !== undefined && object.extent !== null) | ||
* This is an alias of {@link vector_tile.Tile.Layer.fromObject}. | ||
* @function | ||
* @param {Object.<string,*>} object Plain object | ||
@@ -1174,2 +1191,2 @@ * @returns {vector_tile.Tile.Layer} Layer | ||
module.exports = $protobuf.roots["test_vector_tile"] = $root; | ||
module.exports = $root; |
/*eslint-disable block-scoped-var, no-redeclare, no-control-regex, no-prototype-builtins*/ | ||
"use strict"; | ||
var $protobuf = require("../../runtime"); | ||
var $protobuf = require("../../minimal"); | ||
@@ -15,3 +15,3 @@ // Common aliases | ||
// Exported root namespace | ||
var $root = {}; | ||
var $root = $protobuf.roots.test_package || ($protobuf.roots.test_package = {}); | ||
@@ -27,7 +27,5 @@ $root.Package = (function() { | ||
function Package(properties) { | ||
if (properties) { | ||
var keys = Object.keys(properties); | ||
for (var i = 0; i < keys.length; ++i) | ||
if (properties) | ||
for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) | ||
this[keys[i]] = properties[keys[i]]; | ||
} | ||
} | ||
@@ -456,4 +454,7 @@ | ||
message.license = String(object.license); | ||
if (object.repository !== undefined && object.repository !== null) | ||
if (object.repository !== undefined && object.repository !== null) { | ||
if (typeof object.repository !== "object") | ||
throw TypeError(".Package.repository: object expected"); | ||
message.repository = $types[6].fromObject(object.repository); | ||
} | ||
if (object.bugs !== undefined && object.bugs !== null) | ||
@@ -464,2 +465,4 @@ message.bugs = String(object.bugs); | ||
if (object.keywords) { | ||
if (!Array.isArray(object.keywords)) | ||
throw TypeError(".Package.keywords: array expected"); | ||
message.keywords = []; | ||
@@ -472,2 +475,4 @@ for (var i = 0; i < object.keywords.length; ++i) | ||
if (object.bin) { | ||
if (typeof object.bin !== "object") | ||
throw TypeError(".Package.bin: object expected"); | ||
message.bin = {}; | ||
@@ -478,2 +483,4 @@ for (var keys = Object.keys(object.bin), i = 0; i < keys.length; ++i) | ||
if (object.scripts) { | ||
if (typeof object.scripts !== "object") | ||
throw TypeError(".Package.scripts: object expected"); | ||
message.scripts = {}; | ||
@@ -484,2 +491,4 @@ for (var keys = Object.keys(object.scripts), i = 0; i < keys.length; ++i) | ||
if (object.dependencies) { | ||
if (typeof object.dependencies !== "object") | ||
throw TypeError(".Package.dependencies: object expected"); | ||
message.dependencies = {}; | ||
@@ -490,2 +499,4 @@ for (var keys = Object.keys(object.dependencies), i = 0; i < keys.length; ++i) | ||
if (object.optionalDependencies) { | ||
if (typeof object.optionalDependencies !== "object") | ||
throw TypeError(".Package.optionalDependencies: object expected"); | ||
message.optionalDependencies = {}; | ||
@@ -496,2 +507,4 @@ for (var keys = Object.keys(object.optionalDependencies), i = 0; i < keys.length; ++i) | ||
if (object.devDependencies) { | ||
if (typeof object.devDependencies !== "object") | ||
throw TypeError(".Package.devDependencies: object expected"); | ||
message.devDependencies = {}; | ||
@@ -504,2 +517,4 @@ for (var keys = Object.keys(object.devDependencies), i = 0; i < keys.length; ++i) | ||
if (object.cliDependencies) { | ||
if (!Array.isArray(object.cliDependencies)) | ||
throw TypeError(".Package.cliDependencies: array expected"); | ||
message.cliDependencies = []; | ||
@@ -515,2 +530,3 @@ for (var i = 0; i < object.cliDependencies.length; ++i) | ||
* This is an alias of {@link Package.fromObject}. | ||
* @function | ||
* @param {Object.<string,*>} object Plain object | ||
@@ -641,7 +657,5 @@ * @returns {Package} Package | ||
function Repository(properties) { | ||
if (properties) { | ||
var keys = Object.keys(properties); | ||
for (var i = 0; i < keys.length; ++i) | ||
if (properties) | ||
for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) | ||
this[keys[i]] = properties[keys[i]]; | ||
} | ||
} | ||
@@ -768,2 +782,3 @@ | ||
* This is an alias of {@link Package.Repository.fromObject}. | ||
* @function | ||
* @param {Object.<string,*>} object Plain object | ||
@@ -821,2 +836,2 @@ * @returns {Package.Repository} Repository | ||
module.exports = $protobuf.roots["test_package"] = $root; | ||
module.exports = $root; |
/*eslint-disable block-scoped-var, no-redeclare, no-control-regex, no-prototype-builtins*/ | ||
"use strict"; | ||
var $protobuf = require("../../runtime"); | ||
var $protobuf = require("../../minimal"); | ||
@@ -15,3 +15,3 @@ // Common aliases | ||
// Exported root namespace | ||
var $root = {}; | ||
var $root = $protobuf.roots.test_rpc || ($protobuf.roots.test_rpc = {}); | ||
@@ -21,49 +21,27 @@ $root.MyService = (function() { | ||
/** | ||
* RPC implementation passed to services performing a service request on network level, i.e. by utilizing http requests or websockets. | ||
* @typedef RPCImpl | ||
* @type {function} | ||
* @param {$protobuf.Method} method Reflected method being called | ||
* @param {Uint8Array} requestData Request data | ||
* @param {RPCCallback} callback Callback function | ||
* @returns {undefined} | ||
*/ | ||
/** | ||
* Node-style callback as used by {@link RPCImpl}. | ||
* @typedef RPCCallback | ||
* @type {function} | ||
* @param {?Error} error Error, if any, otherwise `null` | ||
* @param {Uint8Array} [responseData] Response data or `null` to signal end of stream, if there hasn't been an error | ||
* @returns {undefined} | ||
*/ | ||
/** | ||
* Constructs a new MyService service. | ||
* @exports MyService | ||
* @extends $protobuf.rpc.Service | ||
* @constructor | ||
* @param {RPCImpl} rpc RPC implementation | ||
* @param {$protobuf.RPCImpl} rpcImpl RPC implementation | ||
* @param {boolean} [requestDelimited=false] Whether requests are length-delimited | ||
* @param {boolean} [responseDelimited=false] Whether responses are length-delimited | ||
*/ | ||
function MyService(rpc, requestDelimited, responseDelimited) { | ||
function MyService(rpcImpl, requestDelimited, responseDelimited) { | ||
$protobuf.rpc.Service.call(this, rpcImpl, requestDelimited, responseDelimited); | ||
} | ||
/** | ||
* RPC implementation. | ||
* @type {RPCImpl} | ||
*/ | ||
this.rpc = rpc; | ||
(MyService.prototype = Object.create($protobuf.rpc.Service.prototype)).constructor = MyService; | ||
/** | ||
* Whether requests are length-delimited. | ||
* @type {boolean} | ||
*/ | ||
this.requestDelimited = Boolean(requestDelimited); | ||
/** | ||
* Creates new MyService service using the specified rpc implementation. | ||
* @param {$protobuf.RPCImpl} rpcImpl RPC implementation | ||
* @param {boolean} [requestDelimited=false] Whether requests are length-delimited | ||
* @param {boolean} [responseDelimited=false] Whether responses are length-delimited | ||
* @returns {MyService} RPC service. Useful where requests and/or responses are streamed. | ||
*/ | ||
MyService.create = function create(rpcImpl, requestDelimited, responseDelimited) { | ||
return new this(rpcImpl, requestDelimited, responseDelimited); | ||
}; | ||
/** | ||
* Whether responses are length-delimited. | ||
* @type {boolean} | ||
*/ | ||
this.responseDelimited = Boolean(responseDelimited); | ||
} | ||
/** | ||
@@ -84,26 +62,14 @@ * Callback as used by {@link MyService#myMethod}. | ||
MyService.prototype.myMethod = function myMethod(request, callback) { | ||
var requestData; | ||
try { | ||
requestData = (this.requestDelimited ? $root.MyRequest.encodeDelimited(request) : $root.MyRequest.encode(request)).finish(); | ||
} catch (err) { | ||
(typeof setImmediate === "function" ? setImmediate : setTimeout)(function() { callback(err); }); | ||
return; | ||
} | ||
var self = this; | ||
this.rpc(myMethod, requestData, function(err, responseData) { | ||
if (err) { | ||
callback(err); | ||
return; | ||
} | ||
var response; | ||
try { | ||
response = self.responseDelimited ? $root.MyResponse.decodeDelimited(responseData) : $root.MyResponse.decode(responseData); | ||
} catch (err2) { | ||
callback(err2); | ||
return; | ||
} | ||
callback(null, response); | ||
}); | ||
return this.rpcCall(myMethod, $root.MyRequest, $root.MyResponse, request, callback); | ||
}; | ||
/** | ||
* Calls MyMethod. | ||
* @name MyService#myMethod | ||
* @function | ||
* @param {MyRequest|Object} request MyRequest message or plain object | ||
* @returns {Promise<MyResponse>} Promise | ||
* @variation 2 | ||
*/ | ||
return MyService; | ||
@@ -121,7 +87,5 @@ })(); | ||
function MyRequest(properties) { | ||
if (properties) { | ||
var keys = Object.keys(properties); | ||
for (var i = 0; i < keys.length; ++i) | ||
if (properties) | ||
for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) | ||
this[keys[i]] = properties[keys[i]]; | ||
} | ||
} | ||
@@ -232,2 +196,3 @@ | ||
* This is an alias of {@link MyRequest.fromObject}. | ||
* @function | ||
* @param {Object.<string,*>} object Plain object | ||
@@ -284,7 +249,5 @@ * @returns {MyRequest} MyRequest | ||
function MyResponse(properties) { | ||
if (properties) { | ||
var keys = Object.keys(properties); | ||
for (var i = 0; i < keys.length; ++i) | ||
if (properties) | ||
for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) | ||
this[keys[i]] = properties[keys[i]]; | ||
} | ||
} | ||
@@ -395,2 +358,3 @@ | ||
* This is an alias of {@link MyResponse.fromObject}. | ||
* @function | ||
* @param {Object.<string,*>} object Plain object | ||
@@ -441,2 +405,2 @@ * @returns {MyResponse} MyResponse | ||
module.exports = $protobuf.roots["test_rpc"] = $root; | ||
module.exports = $root; |
@@ -16,3 +16,3 @@ var tape = require("tape"); | ||
test.equal(root.lookup("Test1.field2").comment, null, "should not parse lines for message fields"); | ||
test.equal(root.lookup("Test1.field3").comment, "Field with a comment.", "should parse triple-slash lines for message fields"); | ||
test.equal(root.lookup("Test1.field3").comment, "Field with a comment and a <a href=\"http://example.com/foo/\">link</a>", "should parse triple-slash lines for message fields"); | ||
@@ -19,0 +19,0 @@ test.equal(root.lookup("Test3").comments.ONE, "Value with a comment.", "should parse blocks for enum values"); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
3814274
11
209
48417
501
- Removed@protobufjs/extend@^1.0.2
- Removed@protobufjs/extend@1.0.2(transitive)