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 | 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 192x 192x 192x 192x 192x 192x 1x 192x 1x 1x 1x 1x 1x 1x 1x 1x 1x 191x 192x 191x 191x 192x 189x 192x 143x 143x 143x 143x 126x 126x 143x 63x 63x 63x 63x 192x 192x 192x 192x 192x 192x 192x 192x 192x 192x 192x 192x 192x 192x 192x 192x 192x 192x 192x | /** @import { Expression, Node, Pattern, Statement, UpdateExpression } from 'estree' */ /** @import { Context } from '../types' */ import { is_ignored } from '../../../../state.js'; import { object } from '../../../../utils/ast.js'; import * as b from '../../../../utils/builders.js'; /** * @param {UpdateExpression} node * @param {Context} context */ export function UpdateExpression(node, context) { const argument = node.argument; if ( argument.type === 'MemberExpression' && argument.object.type === 'ThisExpression' && argument.property.type === 'PrivateIdentifier' && context.state.private_state.has(argument.property.name) ) { let fn = '$.update'; if (node.prefix) fn += '_pre'; /** @type {Expression[]} */ const args = [argument]; if (node.operator === '--') { args.push(b.literal(-1)); } return b.call(fn, ...args); } if (argument.type !== 'Identifier' && argument.type !== 'MemberExpression') { throw new Error('An impossible state was reached'); } const left = object(argument); if (left === null) return context.next(); if (left === argument) { const transform = context.state.transform; const update = transform[left.name]?.update; if (update && Object.hasOwn(transform, left.name)) { return update(node); } } const assignment = /** @type {Expression} */ ( context.visit( b.assignment( node.operator === '++' ? '+=' : '-=', /** @type {Pattern} */ (argument), b.literal(1) ) ) ); const parent = /** @type {Node} */ (context.path.at(-1)); const is_standalone = parent.type === 'ExpressionStatement'; // TODO and possibly others, but not e.g. the `test` of a WhileStatement const update = node.prefix || is_standalone ? assignment : b.binary(node.operator === '++' ? '-' : '+', assignment, b.literal(1)); return is_ignored(node, 'ownership_invalid_mutation') ? b.call('$.skip_ownership_validation', b.thunk(update)) : update; } |