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 1759x 1759x 1759x 1759x 1759x 1759x 1759x 1759x 2x 2x 2x 2x 2x 2x 2x 2x 1808x 1808x 1808x 1808x 1808x 222x 1808x 35x 14x 14x 14x 12x 12x 12x 12x 12x 12x 8x 8x 8x 8x 8x 8x 12x 12x 7x 12x 4x 4x 12x 14x 35x 1797x 1797x 1797x 1808x 585x 585x 585x 1797x 1808x 43x 43x 1754x 1754x 1808x 1749x 1749x 1808x 1808x 1808x 1808x 1808x 1163x 1163x 1163x 1163x 1163x 1163x 1163x 1163x 1163x 1163x 1163x 1163x 1163x 311x 1163x 141x 141x 1163x 1163x 1163x 586x 586x 1808x 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; } |