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 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 1767x 1767x 1767x 1767x 1767x 1767x 1767x 1767x 2x 2x 2x 2x 2x 2x 2x 2x 1816x 1816x 1816x 1816x 1816x 226x 1816x 38x 14x 14x 14x 12x 12x 12x 12x 12x 12x 8x 8x 8x 8x 8x 8x 12x 12x 7x 12x 4x 4x 12x 14x 38x 1805x 1805x 1805x 1816x 589x 589x 589x 1805x 1816x 46x 46x 1759x 1759x 1816x 1754x 1754x 1816x 1816x 1816x 1816x 1816x 1167x 1167x 1167x 1167x 1167x 1167x 1167x 1167x 1167x 1167x 1167x 1167x 1167x 314x 1167x 143x 143x 1167x 1167x 1167x 587x 587x 1816x 245x 245x 245x 245x 245x 245x 245x 245x 245x 342x 342x 342x | /** @import { AssignmentExpression, AssignmentOperator, Expression, Pattern } from 'estree' */ /** @import { Context } from '../types.js' */ import * as b from '../../../../utils/builders.js'; import { build_assignment_value } from '../../../../utils/ast.js'; import { is_ignored } from '../../../../state.js'; import { build_proxy_reassignment, should_proxy } from '../utils.js'; import { visit_assignment_expression } from '../../shared/assignments.js'; /** * @param {AssignmentExpression} node * @param {Context} context */ export function AssignmentExpression(node, context) { const expression = /** @type {Expression} */ ( visit_assignment_expression(node, context, build_assignment) ?? context.next() ); return is_ignored(node, 'ownership_invalid_mutation') ? b.call('$.skip_ownership_validation', b.thunk(expression)) : expression; } /** * @param {AssignmentOperator} operator * @param {Pattern} left * @param {Expression} right * @param {Context} context * @returns {Expression | null} */ function build_assignment(operator, left, right, context) { // Handle class private/public state assignment cases if ( context.state.analysis.runes && left.type === 'MemberExpression' && left.object.type === 'ThisExpression' ) { if (left.property.type === 'PrivateIdentifier') { const private_state = context.state.private_state.get(left.property.name); if (private_state !== undefined) { let transformed = false; let value = /** @type {Expression} */ ( context.visit(build_assignment_value(operator, left, right)) ); if (should_proxy(value, context.state.scope)) { transformed = true; value = private_state.kind === 'raw_state' ? value : build_proxy_reassignment(value, b.member(b.this, private_state.id)); } if (!context.state.in_constructor) { return b.call('$.set', left, value); } else if (transformed) { return b.assignment(operator, /** @type {Pattern} */ (context.visit(left)), value); } } } } let object = left; while (object.type === 'MemberExpression') { // @ts-expect-error object = object.object; } if (object.type !== 'Identifier') { return null; } const binding = context.state.scope.get(object.name); if (!binding) return null; const transform = Object.hasOwn(context.state.transform, object.name) ? context.state.transform[object.name] : null; // reassignment if (object === left && transform?.assign) { let value = /** @type {Expression} */ ( context.visit(build_assignment_value(operator, left, right)) ); // special case — if an element binding, we know it's a primitive const path = context.path.map((node) => node.type); const is_primitive = path.at(-1) === 'BindDirective' && path.at(-2) === 'RegularElement'; if ( !is_primitive && binding.kind !== 'prop' && binding.kind !== 'bindable_prop' && context.state.analysis.runes && should_proxy(value, context.state.scope) ) { value = binding.kind === 'raw_state' ? value : build_proxy_reassignment(value, object); } return transform.assign(object, value); } // mutation if (transform?.mutate) { return transform.mutate( object, b.assignment( operator, /** @type {Pattern} */ (context.visit(left)), /** @type {Expression} */ (context.visit(right)) ) ); } return null; } |