basant307/AI_Governance_Project
048
1"use strict";2module.exports = Root;3 4// extends Namespace5var Namespace = require("./namespace");6((Root.prototype = Object.create(Namespace.prototype)).constructor = Root).className = "Root";7 8var Field = require("./field"),9 Enum = require("./enum"),10 OneOf = require("./oneof"),11 util = require("./util");12 13var Type, // cyclic14 parse, // might be excluded15 common; // "16 17/**18 * Constructs a new root namespace instance.19 * @classdesc Root namespace wrapping all types, enums, services, sub-namespaces etc. that belong together.20 * @extends NamespaceBase21 * @constructor22 * @param {Object.<string,*>} [options] Top level options23 */24function Root(options) {25 Namespace.call(this, "", options);26 27 /**28 * Deferred extension fields.29 * @type {Field[]}30 */31 this.deferred = [];32 33 /**34 * Resolved file names of loaded files.35 * @type {string[]}36 */37 this.files = [];38 39 /**40 * Edition, defaults to proto2 if unspecified.41 * @type {string}42 * @private43 */44 this._edition = "proto2";45 46 /**47 * Global lookup cache of fully qualified names.48 * @type {Object.<string,ReflectionObject>}49 * @private50 */51 this._fullyQualifiedObjects = {};52}53 54/**55 * Loads a namespace descriptor into a root namespace.56 * @param {INamespace} json Namespace descriptor57 * @param {Root} [root] Root namespace, defaults to create a new one if omitted58 * @param {number} [depth] Current nesting depth, defaults to `0`59 * @returns {Root} Root namespace60 */61Root.fromJSON = function fromJSON(json, root, depth) {62 depth = util.checkDepth(depth);63 if (!root)64 root = new Root();65 if (json.options)66 root.setOptions(json.options);67 return root.addJSON(json.nested, depth).resolveAll();68};69 70/**71 * Resolves the path of an imported file, relative to the importing origin.72 * This method exists so you can override it with your own logic in case your imports are scattered over multiple directories.73 * @function74 * @param {string} origin The file name of the importing file75 * @param {string} target The file name being imported76 * @returns {string|null} Resolved path to `target` or `null` to skip the file77 */78Root.prototype.resolvePath = util.path.resolve;79 80/**81 * Fetch content from file path or url82 * This method exists so you can override it with your own logic.83 * @function84 * @param {string} path File path or url85 * @param {FetchCallback} callback Callback function86 * @returns {undefined}87 */88Root.prototype.fetch = util.fetch;89 90// A symbol-like function to safely signal synchronous loading91/* istanbul ignore next */92function SYNC() {} // eslint-disable-line no-empty-function93 94/**95 * Loads one or multiple .proto or preprocessed .json files into this root namespace and calls the callback.96 * @param {string|string[]} filename Names of one or multiple files to load97 * @param {IParseOptions} options Parse options98 * @param {LoadCallback} callback Callback function99 * @returns {undefined}100 */101Root.prototype.load = function load(filename, options, callback) {102 if (typeof options === "function") {103 callback = options;104 options = undefined;105 }106 var self = this;107 if (!callback) {108 return util.asPromise(load, self, filename, options);109 }110 111 var sync = callback === SYNC; // undocumented112 113 // Finishes loading by calling the callback (exactly once)114 function finish(err, root) {115 /* istanbul ignore if */116 if (!callback) {117 return;118 }119 if (sync) {120 throw err;121 }122 if (root) {123 root.resolveAll();124 }125 var cb = callback;126 callback = null;127 cb(err, root);128 }129 130 // Bundled definition existence checking131 function getBundledFileName(filename) {132 var idx = filename.lastIndexOf("google/protobuf/");133 if (idx > -1) {134 var altname = filename.substring(idx);135 if (altname in common) return altname;136 }137 return null;138 }139 140 // Processes a single file141 function process(filename, source, depth) {142 if (depth === undefined)143 depth = 0;144 try {145 if (depth > util.recursionLimit)146 throw Error("max depth exceeded");147 if (util.isString(source) && source.charAt(0) === "{")148 source = JSON.parse(source);149 if (!util.isString(source))150 self.setOptions(source.options).addJSON(source.nested);151 else {152 parse.filename = filename;153 var parsed = parse(source, self, options),154 resolved,155 i = 0;156 if (parsed.imports)157 for (; i < parsed.imports.length; ++i)158 if (resolved = getBundledFileName(parsed.imports[i]) || self.resolvePath(filename, parsed.imports[i]))159 fetch(resolved, false, depth + 1);160 if (parsed.weakImports)161 for (i = 0; i < parsed.weakImports.length; ++i)162 if (resolved = getBundledFileName(parsed.weakImports[i]) || self.resolvePath(filename, parsed.weakImports[i]))163 fetch(resolved, true, depth + 1);164 }165 } catch (err) {166 finish(err);167 }168 if (!sync && !queued) {169 finish(null, self); // only once anyway170 }171 }172 173 // Fetches a single file174 function fetch(filename, weak, depth) {175 if (depth === undefined)176 depth = 0;177 filename = getBundledFileName(filename) || filename;178 179 // Skip if already loaded / attempted180 if (self.files.indexOf(filename) > -1) {181 return;182 }183 self.files.push(filename);184 185 // Shortcut bundled definitions186 if (filename in common) {187 if (sync) {188 process(filename, common[filename], depth);189 } else {190 ++queued;191 setTimeout(function() {192 --queued;193 process(filename, common[filename], depth);194 });195 }196 return;197 }198 199 // Otherwise fetch from disk or network200 if (sync) {201 var source;202 try {203 source = util.fs.readFileSync(filename).toString("utf8");204 } catch (err) {205 if (!weak)206 finish(err);207 return;208 }209 process(filename, source, depth);210 } else {211 ++queued;212 self.fetch(filename, function(err, source) {213 --queued;214 /* istanbul ignore if */215 if (!callback) {216 return; // terminated meanwhile217 }218 if (err) {219 /* istanbul ignore else */220 if (!weak)221 finish(err);222 else if (!queued) // can't be covered reliably223 finish(null, self);224 return;225 }226 process(filename, source, depth);227 });228 }229 }230 var queued = 0;231 232 // Assembling the root namespace doesn't require working type233 // references anymore, so we can load everything in parallel234 if (util.isString(filename)) {235 filename = [ filename ];236 }237 for (var i = 0, resolved; i < filename.length; ++i)238 if (resolved = self.resolvePath("", filename[i]))239 fetch(resolved);240 if (sync) {241 self.resolveAll();242 return self;243 }244 if (!queued) {245 finish(null, self);246 }247 248 return self;249};250// function load(filename:string, options:IParseOptions, callback:LoadCallback):undefined251 252/**253 * Loads one or multiple .proto or preprocessed .json files into this root namespace and calls the callback.254 * @function Root#load255 * @param {string|string[]} filename Names of one or multiple files to load256 * @param {LoadCallback} callback Callback function257 * @returns {undefined}258 * @variation 2259 */260// function load(filename:string, callback:LoadCallback):undefined261 262/**263 * Loads one or multiple .proto or preprocessed .json files into this root namespace and returns a promise.264 * @function Root#load265 * @param {string|string[]} filename Names of one or multiple files to load266 * @param {IParseOptions} [options] Parse options. Defaults to {@link parse.defaults} when omitted.267 * @returns {Promise<Root>} Promise268 * @variation 3269 */270// function load(filename:string, [options:IParseOptions]):Promise<Root>271 272/**273 * Synchronously loads one or multiple .proto or preprocessed .json files into this root namespace (node only).274 * @function Root#loadSync275 * @param {string|string[]} filename Names of one or multiple files to load276 * @param {IParseOptions} [options] Parse options. Defaults to {@link parse.defaults} when omitted.277 * @returns {Root} Root namespace278 * @throws {Error} If synchronous fetching is not supported (i.e. in browsers) or if a file's syntax is invalid279 */280Root.prototype.loadSync = function loadSync(filename, options) {281 if (!util.isNode)282 throw Error("not supported");283 return this.load(filename, options, SYNC);284};285 286/**287 * @override288 */289Root.prototype.resolveAll = function resolveAll() {290 if (!this._needsRecursiveResolve) return this;291 292 if (this.deferred.length)293 throw Error("unresolvable extensions: " + this.deferred.map(function(field) {294 return "'extend " + field.extend + "' in " + field.parent.fullName;295 }).join(", "));296 return Namespace.prototype.resolveAll.call(this);297};298 299// only uppercased (and thus conflict-free) children are exposed, see below300var exposeRe = /^[A-Z]/;301 302/**303 * Handles a deferred declaring extension field by creating a sister field to represent it within its extended type.304 * @param {Root} root Root instance305 * @param {Field} field Declaring extension field witin the declaring type306 * @returns {boolean} `true` if successfully added to the extended type, `false` otherwise307 * @inner308 * @ignore309 */310function tryHandleExtension(root, field) {311 var extendedType = field.parent.lookup(field.extend);312 if (extendedType) {313 var sisterField = new Field(field.fullName, field.id, field.type, field.rule, undefined, field.options);314 //do not allow to extend same field twice to prevent the error315 if (extendedType.get(sisterField.name)) {316 return true;317 }318 sisterField.declaringField = field;319 field.extensionField = sisterField;320 extendedType.add(sisterField);321 return true;322 }323 return false;324}325 326/**327 * Called when any object is added to this root or its sub-namespaces.328 * @param {ReflectionObject} object Object added329 * @returns {undefined}330 * @private331 */332Root.prototype._handleAdd = function _handleAdd(object) {333 if (object instanceof Field) {334 335 if (/* an extension field (implies not part of a oneof) */ object.extend !== undefined && /* not already handled */ !object.extensionField)336 if (!tryHandleExtension(this, object))337 this.deferred.push(object);338 339 } else if (object instanceof Enum) {340 341 if (exposeRe.test(object.name))342 object.parent[object.name] = object.values; // expose enum values as property of its parent343 344 } else if (!(object instanceof OneOf)) /* everything else is a namespace */ {345 346 if (object instanceof Type) // Try to handle any deferred extensions347 for (var i = 0; i < this.deferred.length;)348 if (tryHandleExtension(this, this.deferred[i]))349 this.deferred.splice(i, 1);350 else351 ++i;352 for (var j = 0; j < /* initializes */ object.nestedArray.length; ++j) // recurse into the namespace353 this._handleAdd(object._nestedArray[j]);354 if (exposeRe.test(object.name))355 object.parent[object.name] = object; // expose namespace as property of its parent356 }357 358 if (object instanceof Type || object instanceof Enum || object instanceof Field) {359 // Only store types and enums for quick lookup during resolve.360 this._fullyQualifiedObjects[object.fullName] = object;361 }362 363 // The above also adds uppercased (and thus conflict-free) nested types, services and enums as364 // properties of namespaces just like static code does. This allows using a .d.ts generated for365 // a static module with reflection-based solutions where the condition is met.366};367 368/**369 * Called when any object is removed from this root or its sub-namespaces.370 * @param {ReflectionObject} object Object removed371 * @returns {undefined}372 * @private373 */374Root.prototype._handleRemove = function _handleRemove(object) {375 if (object instanceof Field) {376 377 if (/* an extension field */ object.extend !== undefined) {378 if (/* already handled */ object.extensionField) { // remove its sister field379 object.extensionField.parent.remove(object.extensionField);380 object.extensionField = null;381 } else { // cancel the extension382 var index = this.deferred.indexOf(object);383 /* istanbul ignore else */384 if (index > -1)385 this.deferred.splice(index, 1);386 }387 }388 389 } else if (object instanceof Enum) {390 391 if (exposeRe.test(object.name))392 delete object.parent[object.name]; // unexpose enum values393 394 } else if (object instanceof Namespace) {395 396 for (var i = 0; i < /* initializes */ object.nestedArray.length; ++i) // recurse into the namespace397 this._handleRemove(object._nestedArray[i]);398 399 if (exposeRe.test(object.name))400 delete object.parent[object.name]; // unexpose namespaces401 402 }403 404 delete this._fullyQualifiedObjects[object.fullName];405};406 407// Sets up cyclic dependencies (called in index-light)408Root._configure = function(Type_, parse_, common_) {409 Type = Type_;410 parse = parse_;411 common = common_;412};413 