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 199x 199x 199x 199x 199x 199x 1x 199x 1x 1x 1x 1x 1x 1x 1x 1x 1x 198x 199x 198x 198x 199x 196x 199x 149x 149x 149x 149x 129x 129x 149x 67x 67x 67x 67x 199x 199x 199x 199x 199x 199x 199x 199x 199x 199x 199x 199x 199x 199x 199x 199x 199x 199x 199x | /** @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; } |