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 1762x 1762x 1762x 1762x 1762x 1762x 1762x 1762x 2x 2x 2x 2x 2x 2x 2x 2x 1811x 1811x 1811x 1811x 1811x 225x 1811x 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 1800x 1800x 1800x 1811x 588x 588x 588x 1800x 1811x 46x 46x 1754x 1754x 1811x 1749x 1749x 1811x 1811x 1811x 1811x 1811x 1163x 1163x 1163x 1163x 1163x 1163x 1163x 1163x 1163x 1163x 1163x 1163x 1163x 311x 1163x 141x 141x 1163x 1163x 1163x 586x 586x 1811x 245x 245x 245x 245x 245x 245x 245x 245x 245x 341x 341x 341x | /** @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; } |