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 188x 188x 188x 188x 188x 188x 1x 188x 1x 1x 1x 1x 1x 1x 1x 1x 1x 187x 188x 187x 187x 188x 185x 188x 142x 142x 142x 142x 125x 125x 142x 60x 60x 60x 60x 188x 188x 188x 188x 188x 188x 188x 188x 188x 188x 188x 188x 188x 188x 188x 188x 188x 188x 188x | /** @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; } |