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 201x 201x 201x 201x 201x 201x 1x 201x 1x 1x 1x 1x 1x 1x 1x 1x 1x 200x 201x 200x 200x 201x 198x 201x 150x 150x 150x 150x 129x 129x 150x 69x 69x 69x 69x 201x 201x 201x 201x 201x 201x 201x 201x 201x 201x 201x 201x 201x 201x 201x 201x 201x 201x 201x | /** @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; } |