Skip to content

Commit

Permalink
WIP 1
Browse files Browse the repository at this point in the history
  • Loading branch information
overlookmotel committed Dec 4, 2023
1 parent da6fc34 commit 25bc401
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 45 deletions.
26 changes: 24 additions & 2 deletions lib/instrument/tracking.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@
// Export
module.exports = {
insertBlockVarsIntoBlockStatement,
insertTrackerCodeIntoFunctionBody,
insertTrackerCodeIntoFunctionParams
insertTrackerCodeIntoFunction
};

// Modules
Expand Down Expand Up @@ -50,6 +49,29 @@ function insertBlockVarsIntoBlockStatement(block, blockNode, state) {
blockNode.body.unshift(...statementNodes);
}

/**
* Insert tracker code, scope ID var and temp vars into function.
* If function has complex params, insert into params. Otherwise, into function body.
* @param {Object} fn - Function object
* @param {Object} fnNode - Function AST node
* @param {Object} paramsBlock - Function params block object
* @param {Object} [bodyBlock] - Function body block object
* (`undefined` if arrow function with no body block)
* @param {Object} trackerNode - AST node for tracker call
* @param {Object} state - State object
* @returns {undefined}
*/
function insertTrackerCodeIntoFunction(fn, fnNode, paramsBlock, bodyBlock, trackerNode, state) {
const {firstComplexParamIndex} = fn;
if (firstComplexParamIndex === undefined) {
insertTrackerCodeIntoFunctionBody(fnNode, paramsBlock, bodyBlock, trackerNode, state);
} else {
insertTrackerCodeIntoFunctionParams(
fnNode, paramsBlock, bodyBlock, trackerNode, firstComplexParamIndex, state
);
}
}

/**
* Insert tracker code, scope ID var and temp vars into function body.
* @param {Object} fnNode - Function AST node
Expand Down
10 changes: 6 additions & 4 deletions lib/instrument/visitors/class.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const t = require('@babel/types');
// Imports
const {
createFunction, createAndEnterFunctionOrClassNameBlock, visitFunctionParams, visitFunctionBody,
removeUnnecessaryUseStrictDirectives, insertTrackerComment, instrumentFunctionOrClassConstructor
removeUnnecessaryUseStrictDirectives, insertTrackerComment, createTracker
} = require('./function.js'),
{visitMethod, getMethodName} = require('./method.js'),
Expression = require('./expression.js'),
Expand All @@ -28,6 +28,7 @@ const {
createBlockId, createBlock, createBlockWithId, createAndEnterBlock, createBindingWithoutNameCheck,
createThisBinding, createArgumentsBinding, createNewTargetBinding
} = require('../blocks.js'),
{insertTrackerCodeIntoFunction} = require('../tracking.js'),
{visitKey, visitKeyMaybe, visitKeyContainer} = require('../visit.js'),
{createTempVarNode} = require('../internalVars.js'),
{FN_TYPE_CLASS} = require('../../shared/constants.js');
Expand Down Expand Up @@ -447,8 +448,9 @@ function instrumentClass(
parent[key] = classNode;

// Add tracker code + block vars to constructor
instrumentFunctionOrClassConstructor(
constructorNode, fn, constructorParamsBlock, constructorBodyBlock, state
const trackerNode = createTracker(fn, state);
insertTrackerCodeIntoFunction(
fn, constructorNode, constructorParamsBlock, constructorBodyBlock, trackerNode, state
);

// Insert tracking comment
Expand All @@ -460,7 +462,7 @@ function instrumentClass(

/**
* Create empty class constructor node.
* It will be instrumented by `instrumentFunctionOrClassConstructor()`, same as a real constructor.
* It will be instrumented by `instrumentClass()`, same as a real constructor.
* @param {Object} fn - Function object for class
* @param {Object} state - State object
* @returns {Object} - Class constructor AST node
Expand Down
52 changes: 13 additions & 39 deletions lib/instrument/visitors/function.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ module.exports = {
escapeFilename,
withStrictModeState,
hoistSloppyFunctionDeclarations,
instrumentFunctionOrClassConstructor,
createTracker,
insertTrackerComment,
createFunctionInfoFunction
};
Expand All @@ -38,7 +38,7 @@ const Statement = require('./statement.js'),
createBlock, createAndEnterBlock, createBinding, createThisBinding, createArgumentsBinding,
createNewTargetBinding, getOrCreateExternalVar
} = require('../blocks.js'),
{insertTrackerCodeIntoFunctionBody, insertTrackerCodeIntoFunctionParams} = require('../tracking.js'),
{insertTrackerCodeIntoFunction} = require('../tracking.js'),
{createFnInfoVarNode} = require('../internalVars.js'),
{insertComment, hasUseStrictDirective, stringLiteralWithSingleQuotes} = require('../utils.js'),
{combineArraysWithDedup} = require('../../shared/functions.js'),
Expand Down Expand Up @@ -613,27 +613,23 @@ function instrumentFunction(node, fn, parent, key, paramsBlock, bodyBlock, state
// Restore to original place in AST
parent[key] = node;

instrumentFunctionOrClassConstructor(node, fn, paramsBlock, bodyBlock, state);
// Insert tracker call and block vars (`livepack_scopeId` and `livepack_temp`) into function.
// NB: `bodyBlock` here may actually be params block if is an arrow function with no body.
const trackerNode = createTracker(fn, state);
insertTrackerCodeIntoFunction(fn, node, paramsBlock, bodyBlock, trackerNode, state);

if (node.type === 'ArrowFunctionExpression') insertArrowFunctionTrackerComment(fn, node, state);
}

/**
* Instrument function, method or class constructor.
* - Insert `livepack_tracker()` call in function body.
* - Insert block vars (`livepack_scopeId`, `livepack_temp`) in function body or params.
* - Create function info function containing function AST, details of internal and external vars etc.
*
* @param {Object} node - Function, method, or class constructor AST node
* Create tracker call.
* Create scopes array, and also copy external vars down to parent function.
* @param {Object} fn - Function object
* @param {Object} paramsBlock - Function's params block object
* @param {Object} bodyBlock - Function's body block object
* @param {Object} state - State object
* @returns {undefined}
* @returns {Object} - AST node for tracker call
*/
function instrumentFunctionOrClassConstructor(node, fn, paramsBlock, bodyBlock, state) {
// NB `bodyBlock` here may actually be params block if is an arrow function with no body.
// Sort scopes in ascending order of block ID.
function createTracker(fn, state) {
// Sort scopes in ascending order of block ID
const scopes = [...fn.externalVars].map(([block, vars]) => ({block, vars}))
.sort((scope1, scope2) => (scope1.block.id > scope2.block.id ? 1 : -1));
fn.scopes = scopes;
Expand All @@ -650,31 +646,9 @@ function instrumentFunctionOrClassConstructor(node, fn, paramsBlock, bodyBlock,
}
}

// Insert tracker call and block vars (`livepack_scopeId` and `livepack_temp`) into function.
// If function has complex params, insert into params. Otherwise, into function body.
const trackerNode = createTrackerCall(fn.id, scopes, state);

const {firstComplexParamIndex} = fn;
if (firstComplexParamIndex === undefined) {
insertTrackerCodeIntoFunctionBody(node, paramsBlock, bodyBlock, trackerNode, state);
} else {
insertTrackerCodeIntoFunctionParams(
node, paramsBlock, bodyBlock, trackerNode, firstComplexParamIndex, state
);
}
}

/**
* Create tracker call.
* @param {number} fnId - Function ID
* @param {Array<Object>} scopes - Array of scope objects in ascending order of block ID
* @param {Object} state - State object
* @returns {Object} - AST node for tracker call
*/
function createTrackerCall(fnId, scopes, state) {
// `livepack_tracker(livepack_getFnInfo_3, () => [[livepack_scopeId_2, x]]);`
// `livepack_tracker(livepack_getFnInfo_3, () => [[livepack_scopeId_2, x]])`
return t.callExpression(state.trackerVarNode, [
createFnInfoVarNode(fnId, state),
createFnInfoVarNode(fn.id, state),
t.arrowFunctionExpression([], t.arrayExpression(
scopes.map(scope => t.arrayExpression([
scope.block.varsBlock.scopeIdVarNode,
Expand Down

0 comments on commit 25bc401

Please sign in to comment.