• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

overlookmotel / livepack / 7161585751

11 Dec 2023 01:08AM UTC coverage: 90.568% (-0.02%) from 90.588%
7161585751

push

github

overlookmotel
Instrument: Replace `bindings` object with Map [perf]

4683 of 5038 branches covered (0.0%)

Branch coverage included in aggregate %.

22 of 27 new or added lines in 9 files covered. (81.48%)

7 existing lines in 4 files now uncovered.

12524 of 13961 relevant lines covered (89.71%)

8689.33 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.12
/lib/instrument/blocks.js
1
/* --------------------
62✔
2
 * livepack module
62✔
3
 * Code instrumentation block functions
62✔
4
 * ------------------*/
62✔
5

62✔
6
'use strict';
62✔
7

62✔
8
// Export
62✔
9
module.exports = {
62✔
10
        createBlock,
62✔
11
        createBlockWithId,
62✔
12
        createAndEnterBlock,
62✔
13
        createBlockId,
62✔
14
        createBinding,
62✔
15
        createBindingWithoutNameCheck,
62✔
16
        createThisBinding,
62✔
17
        createArgumentsBinding,
62✔
18
        createNewTargetBinding,
62✔
19
        getOrCreateExternalVar,
62✔
20
        activateBlock,
62✔
21
        activateBinding,
62✔
22
        createBlockTempVar
62✔
23
};
62✔
24

62✔
25
// Modules
62✔
26
const t = require('@babel/types');
62✔
27

62✔
28
// Imports
62✔
29
const {
62✔
30
                createScopeIdVarNode, createTempVarNode, checkInternalVarNameClash
62✔
31
        } = require('./internalVars.js'),
62✔
32
        {createArrayOrPush} = require('../shared/functions.js');
62✔
33

62✔
34
// Exports
62✔
35

62✔
36
/**
62✔
37
 * Create block.
62✔
38
 * @param {string} [name] - Block name
62✔
39
 * @param {boolean} isVarsBlock - `true` if is a vars block
62✔
40
 * @param {Object} state - State object
62✔
41
 * @returns {Object} - Block object
62✔
42
 */
62✔
43
function createBlock(name, isVarsBlock, state) {
83,082✔
44
        return createBlockWithId(createBlockId(state), name, isVarsBlock, state);
83,082✔
45
}
83,082✔
46

62✔
47
/**
62✔
48
 * Create block with specified ID.
62✔
49
 * @param {number} id - Block ID
62✔
50
 * @param {string} [name] - Block name
62✔
51
 * @param {boolean} isVarsBlock - `true` if is a vars block
62✔
52
 * @param {Object} state - State object
156✔
53
 * @returns {Object} - Block object
156✔
54
 */
156✔
55
function createBlockWithId(id, name, isVarsBlock, state) {
88,196✔
56
        const parent = state.currentBlock;
88,196✔
57
        const block = {
×
58
                id,
×
59
                name,
88,196✔
60
                parent,
88,196✔
61
                bindings: new Map(), // Keyed by binding name
88,196✔
62
                varsBlock: undefined,
88,196✔
63
                scopeIdVarNode: undefined,
88,196✔
64
                tempVarNodes: undefined
88,196✔
65
        };
88,196✔
66
        block.varsBlock = isVarsBlock ? block : parent.varsBlock;
88,196✔
67
        return block;
88,196✔
68
}
88,196✔
69

62✔
70
/**
62✔
71
 * Create block and enter it.
62✔
72
 * @param {string} [name] - Block name
62✔
73
 * @param {boolean} isVarsBlock - `true` if is a vars block
62✔
74
 * @param {Object} state - State object
156✔
75
 * @returns {Object} - Block object
156✔
76
 */
156✔
77
function createAndEnterBlock(name, isVarsBlock, state) {
59,292✔
78
        // eslint-disable-next-line no-return-assign
59,292✔
79
        return state.currentBlock = createBlock(name, isVarsBlock, state);
59,292✔
80
}
59,292✔
81

156✔
82
/**
156✔
83
 * Create unique block ID.
156✔
84
 * @param {Object} state - State object
156✔
85
 * @returns {number} - Block ID
156✔
86
 */
156✔
87
function createBlockId(state) {
89,202✔
88
        return state.nextBlockId++;
89,202✔
89
}
89,202✔
90

156✔
91
/**
156✔
92
 * Create binding for variable in block.
156✔
93
 * Also check if `varName` potentially clashes with Livepack's internal vars.
62✔
94
 *
62✔
95
 * @param {Object} block - Block object
62✔
96
 * @param {string} varName - Variable name
62✔
97
 * @param {Object} props - Properties object
62✔
98
 * @param {boolean} [props.isConst=false] - `true` if is const
62✔
99
 * @param {boolean} [props.isSilentConst=false] - `true` if is function expression name,
98✔
100
 *   assignment to which fails silently in sloppy mode
98✔
101
 * @param {boolean} [props.isVar=false] - `true` if defined with `var` statement or function declaration
98✔
102
 * @param {boolean} [props.isFrozenName=false] - `true` if is var which is not renamed when used
62✔
103
 *   inside function in which it's bound
62✔
104
 * @param {Array<string>} [props.argNames] - Linked argument names (only relevant for `arguments`)
62✔
105
 * @param {Object} state - State object
186✔
106
 * @returns {Object} - Binding object
186✔
107
 */
186✔
108
function createBinding(block, varName, props, state) {
58,348✔
109
        checkInternalVarNameClash(varName, state);
58,348✔
110
        return createBindingWithoutNameCheck(block, varName, props);
58,348✔
111
}
58,348✔
112

62✔
113
/**
62✔
114
 * Create binding for variable in block.
62✔
115
 * Do not check if `varName` potentially clashes with Livepack's internal vars.
62✔
116
 * Intended to be called for vars which it's known are non-clashing e.g. `arguments`.
62✔
117
 *
62✔
118
 * @param {Object} block - Block object
62✔
119
 * @param {string} varName - Variable name
62✔
120
 * @param {Object} props - Properties object
62✔
121
 * @param {Object} [props.varNode] - Identifier AST node for var which will go in tracker function call
62✔
122
 * @param {boolean} [props.isConst=false] - `true` if is const
62✔
123
 * @param {boolean} [props.isSilentConst=false] - `true` if is function expression name,
62✔
124
 *   assignment to which fails silently in sloppy mode
62✔
125
 * @param {boolean} [props.isVar=false] - `true` if defined with `var` statement or function declaration
62✔
126
 * @param {boolean} [props.isFrozenName=false] - `true` if is var which is not renamed when used
64✔
127
 *   inside function in which it's bound
64✔
128
 * @param {Array<string>} [props.argNames] - Linked argument names (only relevant for `arguments`)
64✔
129
 * @returns {Object} - Binding object
64✔
130
 */
64✔
131
function createBindingWithoutNameCheck(block, varName, props) {
133,560✔
132
        const binding = {
133,560✔
133
                name: varName,
133,560✔
134
                varNode: props.varNode,
133,560✔
135
                isConst: !!props.isConst,
133,560✔
136
                isSilentConst: !!props.isSilentConst,
133,560✔
137
                isVar: !!props.isVar,
133,560✔
138
                isFrozenName: !!props.isFrozenName,
133,560✔
139
                argNames: props.argNames,
133,560✔
140
                trails: [] // Trails of usages within same function as binding, where var not frozen
133,560✔
141
        };
133,560✔
142
        block.bindings.set(varName, binding);
133,560✔
143
        return binding;
133,560✔
144
}
133,560✔
145

62✔
146
/**
62✔
147
 * Create binding for `this`.
62✔
148
 * @param {Object} block - Block object
62✔
149
 * @returns {Object} - Binding object
62✔
150
 */
62✔
151
function createThisBinding(block) {
20,006✔
152
        // `isFrozenName: true` because it cannot be renamed within function in which it's created
20,006✔
153
        return createBindingWithoutNameCheck(
20,006✔
154
                // eslint-disable-next-line no-use-before-define
20,006✔
155
                block, 'this', {varNode: thisNode, isConst: true, isFrozenName: true}
20,006✔
156
        );
20,006✔
157
}
20,006✔
158

62✔
159
const thisNode = t.thisExpression();
62✔
160

62✔
161
/**
62✔
162
 * Create binding for function `arguments`.
62✔
163
 * @param {Object} block - Block object
62✔
164
 * @param {boolean} isConst - `true` if is const (strict mode)
62✔
165
 * @param {Array<string>} argNames - Linked argument names
62✔
166
 * @returns {Object} - Binding object
62✔
167
 */
150✔
168
function createArgumentsBinding(block, isConst, argNames) {
18,598✔
169
        // `isFrozenName: true` because it cannot be renamed within function in which it's created
18,598✔
170
        return createBindingWithoutNameCheck(block, 'arguments', {isConst, isFrozenName: true, argNames});
18,598✔
171
}
18,598✔
172

150✔
173
/**
150✔
174
 * Create binding for `new.target`.
150✔
175
 * @param {Object} block - Block object
150✔
176
 * @returns {Object} - Binding object
150✔
177
 */
150✔
178
function createNewTargetBinding(block) {
20,006✔
179
        // `isFrozenName: true` because it cannot be renamed within function in which it's created
20,006✔
180
        /* eslint-disable no-use-before-define */
20,006✔
181
        newTargetNode ||= t.metaProperty(t.identifier('new'), t.identifier('target'));
20,006✔
182
        return createBindingWithoutNameCheck(
20,006✔
183
                block, 'new.target', {varNode: newTargetNode, isConst: true, isFrozenName: true}
20,006✔
184
        );
28✔
185
        /* eslint-enable no-use-before-define */
28✔
186
}
28✔
187

28✔
188
let newTargetNode;
28✔
189

28✔
190
/**
28✔
191
 * Get or create an external var in a function.
28✔
UNCOV
192
 * @param {Object} fn - Function object
×
193
 * @param {Object} block - Block object
28✔
194
 * @param {string} varName - Var name
28✔
195
 * @param {Object} binding - Binding object
28✔
196
 * @returns {Object} - External var object
28✔
197
 */
28✔
198
function getOrCreateExternalVar(fn, block, varName, binding) {
46,998✔
199
        let blockVars = fn.externalVars.get(block),
46,998✔
200
                externalVar;
46,998✔
201
        if (blockVars) {
46,998✔
202
                externalVar = blockVars[varName];
27,688✔
203
        } else {
46,422✔
204
                blockVars = Object.create(null);
19,310✔
205
                fn.externalVars.set(block, blockVars);
19,310✔
206
        }
19,310✔
207

46,998✔
208
        if (!externalVar) {
46,998✔
209
                externalVar = {
33,572✔
210
                        binding,
33,572✔
211
                        isReadFrom: false,
33,572✔
212
                        isAssignedTo: false,
33,572✔
213
                        isFrozenName: fn.containsEval,
33,572✔
214
                        trails: []
24✔
215
                };
24✔
216
                blockVars[varName] = externalVar;
24✔
217
        }
24✔
218
        return externalVar;
24✔
219
}
24✔
220

24✔
221
/**
24✔
222
 * Activate block.
24✔
223
 * Called when block contains a binding which is referenced within a function.
24✔
224
 * @param {Object} block - Block object
×
225
 * @param {Object} state - State object
24✔
226
 * @returns {undefined}
24✔
227
 */
24✔
228
function activateBlock(block, state) {
36,066✔
229
        const {varsBlock} = block;
36,066✔
230
        if (!varsBlock.scopeIdVarNode) varsBlock.scopeIdVarNode = createScopeIdVarNode(varsBlock.id, state);
36,066✔
231
}
36,066✔
232

62✔
233
/**
62✔
234
 * Activate binding.
62✔
235
 * Called when a binding is accessed from within a function.
62✔
236
 * @param {Object} binding - Binding object
62✔
237
 * @returns {undefined}
28✔
238
 */
28✔
239
function activateBinding(binding) {
35,104✔
240
        if (!binding.varNode) binding.varNode = t.identifier(binding.name);
35,104✔
241
}
×
242

×
243
/**
×
244
 * Create temp var in block.
×
UNCOV
245
 * @param {Object} block - Block object
×
246
 * @param {Object} state - State object
28✔
247
 * @returns {undefined}
28✔
248
 */
28✔
249
function createBlockTempVar(block, state) {
484✔
250
        const tempVarNode = createTempVarNode(state);
484✔
251
        createArrayOrPush(block.varsBlock, 'tempVarNodes', tempVarNode);
484✔
252
        return tempVarNode;
484✔
253
}
484✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc