All files / mframejs/binding createBindingExpression.ts

90.91% Statements 50/55
70% Branches 14/20
75% Functions 3/4
90.91% Lines 50/55

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 15429x 29x 29x   29x 29x 29x               29x   4613x                   3392x 3392x   3266x 3266x 3266x 3266x 3266x       126x 126x 126x 126x   126x 381x     128x 128x   13x 13x         13x                           56x 56x 56x 56x             72x 72x 72x 72x   126x                   3392x 3431x                                     3431x           3392x   1221x       4613x 4696x 4696x       4613x 4613x                     29x   2015x 2015x 2021x 2021x        
import { tokenize } from './ast/tokenize';
import { generateAST } from './ast/generateAst';
import { ClassPropertyObserverCreator } from './property/classPropertyObserverCreator';
import { PropertyObserverHandler } from './property/propertyObserverHandler';
import { Cache } from '../utils/exported';
import { CONSTANTS, IBindingContext } from '../interface/exported';
import { getCorrectContext } from './contextOfObject';
 
 
 
/**
 * creates binding expression by getting tokens from the text
 *
 */
export function createBindingExpression(expression: string, _class: IBindingContext, setterClass: PropertyObserverHandler) {
 
    let attributesValues: any[] = [];
    let ast;
 
    if (expression) {
 
        if (!setterClass.attributesValues) {
 
 
 
            let tokens: any;
            let tokenValues: any = [];
            let tokenObject: any = [];
            if (Cache.expressionMap.has(expression)) {
                const cacheX = Cache.expressionMap.get(expression);
                ast = (<any>cacheX).ast;
                tokens = (<any>cacheX).tokens;
                tokenValues = (<any>cacheX).tokenValues;
                tokenObject = (<any>cacheX).tokenObject;
 
 
            } else {
                tokens = tokenize(expression);
                ast = generateAST(tokens);
                let curVal: any = null;
                let curObject: any = [];
 
                for (let next = 0; next < tokens.length; next++) {
                    const tok = tokens[next];
                    if (tok.type === 'variable') {
                        if (!curVal) {
                            curVal = tok.value;
                            curObject.push(tok.value);
                        } else {
                            curVal = curVal + tok.value;
                            curObject.push(tok.value);
                        }
                    } else {
                        if (tok.type === 'operator' && tok.value === '.') {
                            if (curVal) {
                                curVal = curVal + '.';
                            }
                        } else {
                            if (tok.type === 'operator' // support binding to "somevalue.array[0].name"
                                && tok.value === '['
                                && tokens[next + 2]
                                && tokens[next + 2].type === 'operator'
                                && tokens[next + 2].value === ']') {
                                if (curVal) {
                                    curVal = curVal + '[' + tokens[next + 1].value + ']';
                                }
                                next = next + 2;
                            } else {
                                if (curVal) {
                                    tokenValues.push(curVal);
                                    curVal = null;
                                    tokenObject.push(curObject);
                                    curObject = [];
                                }
                            }
                        }
                    }
                }
                if (curVal) {
                    tokenValues.push(curVal);
                    tokenObject.push(curObject);
                    curObject = [];
                    curVal = null;
                }
                Cache.expressionMap.set(expression, {
                    ast: ast,
                    tokens: tokens,
                    tokenValues: tokenValues,
                    tokenObject: tokenObject
                });
            }
 
 
            // for each token get the attribute on variables
            tokenValues.forEach((tok: any) => {
                const newctx = getCorrectContext(tok, _class);
 
 
                if (typeof tok === 'string'
                    && tok[0] !== '$'
                    && newctx
                    && newctx.__bindingContext
                    && newctx.$context.__proto__
                    && newctx.$context.__proto__[CONSTANTS.META_COMPUTEDFROM]
                    && newctx.$context.__proto__[CONSTANTS.META_COMPUTEDFROM][tok]) {
                    const computedFrom = newctx.$context.__proto__[CONSTANTS.META_COMPUTEDFROM];
                    computedFrom[tok].attributes.forEach((val: any) => {
                        if (attributesValues.indexOf(val) === -1) {
                            attributesValues.push(val);
                        }
 
                    });
                } else {
                    if (attributesValues.indexOf(tok) === -1) {
                        attributesValues.push(tok);
                    }
                }
            });
 
            // set ast to setter
            setterClass.setAst(ast);
        } else {
            attributesValues = setterClass.attributesValues;
        }
 
        // for each attribute found
        for (let i = 0; i < attributesValues.length; i++) {
            const newctx = getCorrectContext(attributesValues[i], _class);
            ClassPropertyObserverCreator.create(newctx || _class, attributesValues[i], setterClass);
        }
 
        // initiate setter class
        setterClass.init();
        setterClass.attributesValues = attributesValues;
    }
 
}
 
 
 
/**
 * remove binding expression
 *
 */
export function removeBindingExpression(text: string, _class: IBindingContext, handlerClass: PropertyObserverHandler) {
    if (text && handlerClass.attributesValues) {
        const attributesValues = handlerClass.attributesValues;
        for (let i = 0; i < attributesValues.length; i++) {
            const newctx = getCorrectContext(attributesValues[i], _class);
            ClassPropertyObserverCreator.remove(newctx || _class, attributesValues[i], handlerClass);
        }
    }
}