Assign short symbols to the most frequent identifiers first. Identifiers with an ``X``/``X__impl`` twin are kept in lockstep: when ``X`` is mapped to ``$a``, ``X__impl`` is mapped to ``$a__impl``. This preserves runtime ``methodId + "__impl"`` concatenation patterns in port.js (e.g.
(counts: Counter)
| 428 | |
| 429 | |
| 430 | def build_mapping(counts: Counter) -> dict[str, str]: |
| 431 | """Assign short symbols to the most frequent identifiers first. |
| 432 | |
| 433 | Identifiers with an ``X``/``X__impl`` twin are kept in lockstep: |
| 434 | when ``X`` is mapped to ``$a``, ``X__impl`` is mapped to |
| 435 | ``$a__impl``. This preserves runtime ``methodId + "__impl"`` |
| 436 | concatenation patterns in port.js (e.g. ctor lookup, CN1SS hooks) |
| 437 | without requiring a lookup table. |
| 438 | |
| 439 | We only mangle when the mangled form is strictly shorter than the |
| 440 | original — otherwise skipping leaves the source slightly larger but |
| 441 | avoids bloating identifiers whose original name was already short. |
| 442 | """ |
| 443 | names = set(counts.keys()) |
| 444 | # Bases: names without __impl suffix (plus __impl names whose base is |
| 445 | # not present — orphans that can mangle freely). |
| 446 | pairs: dict[str, str | None] = {} |
| 447 | for name in sorted(names): |
| 448 | if name.endswith(_IMPL_SUFFIX): |
| 449 | base = name[: -len(_IMPL_SUFFIX)] |
| 450 | if base in names: |
| 451 | # handled via its base entry below |
| 452 | continue |
| 453 | # Orphan impl — mangle on its own; no twin exists in this bundle |
| 454 | pairs[name] = None |
| 455 | continue |
| 456 | impl = name + _IMPL_SUFFIX |
| 457 | pairs[name] = impl if impl in names else None |
| 458 | |
| 459 | def rank_key(base: str) -> tuple[int, str]: |
| 460 | impl = pairs.get(base) |
| 461 | total = counts[base] |
| 462 | if impl: |
| 463 | total += counts.get(impl, 0) |
| 464 | return (-total, base) |
| 465 | |
| 466 | mapping: dict[str, str] = {} |
| 467 | rank = 0 |
| 468 | for base in sorted(pairs.keys(), key=rank_key): |
| 469 | impl = pairs[base] |
| 470 | short = symbol_for(rank) |
| 471 | rank += 1 |
| 472 | base_saves = len(short) < len(base) |
| 473 | if impl: |
| 474 | impl_short = short + _IMPL_SUFFIX |
| 475 | impl_saves = len(impl_short) < len(impl) |
| 476 | else: |
| 477 | impl_short = None |
| 478 | impl_saves = False |
| 479 | # Mangle the pair atomically: either both move to the short form |
| 480 | # or neither does. Splitting would break ``X + "__impl"`` lookups |
| 481 | # at runtime (the mangled base would resolve but the appended |
| 482 | # suffix would name a non-existent global). |
| 483 | if impl is not None and not (base_saves and impl_saves): |
| 484 | continue |
| 485 | if impl is None and not base_saves: |
| 486 | continue |
| 487 | mapping[base] = short |
no test coverage detected