UNPKG

targaryen

Version:

Test Firebase security rules without connecting to Firebase.

96 lines (74 loc) 2.46 kB
/** * Node handling tertiary expressions validation and evaluation. * * Validate the test and the two consequences nodes. * * The test inferred type must be boolean and cannot be delayed. There is no * requirement of the tertiary inferred type; it can be anything. * */ 'use strict'; const base = require('./base'); const types = require('../types'); const Node = base.Node; class ConditionalNode extends Node { init(source, astNode, scope) { this.test = Node.from(source, astNode.test, scope); this.consequent = Node.from(source, astNode.consequent, scope); this.alternate = Node.from(source, astNode.alternate, scope); } /** * Infer type of a conditional node. * * The test must inferred to a boolean. * * The two branches can have any type; they don't need to be identical. * * @return {string|FuncSignature} */ inferType() { const mustComply = true; const msg = ' condition of ? must be boolean.'; this.assertType(this.test.inferredType, 'boolean', {mustComply, msg}); const consequent = this.consequent.inferredType; const alternate = this.alternate.inferredType; if (consequent === alternate) { return consequent; } const isPrimitive = types.isPrimitive(consequent) && types.isPrimitive(alternate); return isPrimitive ? 'primitive' : 'any'; } evaluate(state) { const test = this.test.evaluate(state); return test === true ? this.consequent.evaluate(state) : this.alternate.evaluate(state); } debug(state, cb) { const test = this.test.debug(state, cb); let value, consequent, alternate; if (test.value === true) { consequent = this.consequent.debug(state, cb); alternate = {detailed: this.alternate.toString()}; value = consequent.value; } else { alternate = this.alternate.debug(state, cb); consequent = {detailed: this.consequent.toString()}; value = alternate.value; } const detailed = ( `${test.detailed} [=> ${test.value}] ?\n` + ` ${consequent.detailed} [=> ${consequent.value}] :\n` + ` ${alternate.detailed} [=> ${alternate.value}]\n` ); cb({ type: this.astNode.type, original: this.original, detailed, value }); return {detailed, value}; } toString() { return `${this.test} ?\n ${this.consequent} :\n ${this.alternate}`; } } Node.register('ConditionalExpression', ConditionalNode);