{"id":28573813,"url":"https://github.com/chromedevtools/sourcemap-scopes-encoding","last_synced_at":"2026-02-08T13:02:09.931Z","repository":{"id":264631458,"uuid":"893786710","full_name":"ChromeDevTools/sourcemap-scopes-encoding","owner":"ChromeDevTools","description":null,"archived":false,"fork":false,"pushed_at":"2025-01-30T10:39:44.000Z","size":19310,"stargazers_count":1,"open_issues_count":1,"forks_count":2,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-07-19T19:23:46.988Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ChromeDevTools.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-11-25T08:00:03.000Z","updated_at":"2025-03-11T16:43:12.000Z","dependencies_parsed_at":"2025-01-30T11:35:51.451Z","dependency_job_id":null,"html_url":"https://github.com/ChromeDevTools/sourcemap-scopes-encoding","commit_stats":null,"previous_names":["chromedevtools/sourcemap-scopes-encoding"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ChromeDevTools/sourcemap-scopes-encoding","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ChromeDevTools%2Fsourcemap-scopes-encoding","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ChromeDevTools%2Fsourcemap-scopes-encoding/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ChromeDevTools%2Fsourcemap-scopes-encoding/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ChromeDevTools%2Fsourcemap-scopes-encoding/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ChromeDevTools","download_url":"https://codeload.github.com/ChromeDevTools/sourcemap-scopes-encoding/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ChromeDevTools%2Fsourcemap-scopes-encoding/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29230723,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-08T12:28:20.184Z","status":"ssl_error","status_checked_at":"2026-02-08T12:28:19.510Z","response_time":57,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-10T21:19:26.401Z","updated_at":"2026-02-08T13:02:09.914Z","avatar_url":"https://github.com/ChromeDevTools.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Source Map \"Scopes\" encoding comparison\n\nThis repository implements various ideas for encoding\n[source map scopes](https://github.com/tc39/source-map/blob/main/proposals/scopes.md).\nThe goal is to evaluate different encoding schemes w.r.t. complexity, size and\nextensibility.\n\n## Comparing different encoding schemes\n\nThe repository includes a simple tool that compares the different encoding\nschemes against each other. It takes as input a list of source maps and a list\nof encoding schemes, and it spits out the size of the resulting source map\n(uncompressed, gzip, brotli). The input source maps require scope information in\nthe format of the current proposal.\n\nUsage:\n\n```\ndeno -R src/main.ts [OPTIONS] FILES...\n\nOptions:\n        --proposal              Include the \"Proposal\" encoding schemes\n        --prefix                Include the \"Prefix\" encoding scheme (Option A)\n        --remaining             Include the \"Remaining\" encoding scheme (Option B)\n        --tag-split             Include the \"Tag Split\" encoding scheme (Option C)\n        --tag-combined          Include the \"Tag Combined\" encoding scheme (Option D)\n        --sizes \u003carg\u003e           How to calculate the sizes/deltas. Valid values are:\n                                \"scopes\" (default). Include only scopes related source map fields (without names, mappings).\n                                \"map\". Include the whole source map, including names, mappings and sources (content).\n        --sizes-reference \u003carg\u003e The baseline for the delta calculation. Useful to estimate the\n                                size impact of the encoding schemes in general relative to source\n                                maps with/without \"names\" mappings.\n                                Valid values are:\n                                \"proposal\" (default). Compare against the input source map with\n                                    the \"proposal\" encoding scheme.\n                                \"no-scopes\". Only valid with \"--sizes=map\". Compare against the\n                                    input source map without scopes related fields.\n                                \"no-names\". Only valid with \"--sizes=map\". Compare against the\n                                    input source map without scopes related fields and \"names\"\n                                    stripped from mappings.\n        --verify                Internal. Round-trip decode each encoding scheme and compare the result against the input codec.\n```\n\n## Source map examples\n\nThe scope information in the `./examples` directory are obtained with a\ncustomized [terser](https://github.com/terser/terser). The customized terser\nsupports basic function and block scopes, as well as variable renaming.\n\nThe examples are:\n\n- _simple.min.js.map_: Two tiny scripts with two simple functions.\n- _common.min.js.map_: The `front_end/core/common` module the Chrome DevTools\n  repository.\n- _sdk.min.js.map_: The `front_end/core/sdk` module from the Chrome DevTools\n  repository.\n- _typescript.min.js.map_: The `lib/typescript.js` file from the tsc node\n  module.\n\n## Results\n\n```\nTask all deno -R src/main.ts --proposal --prefix --remaining --tag-split --tag-combined --tag-variables ./examples/simple.min.js.map ./examples/common.min.js.map ./examples/sdk.min.js.map ./examples/typescript.min.js.map\nName:         Proposal\nDescription:  The currently proposed \"Scopes\" (stage 3) encoding\n\nName:         Proposal (unsigned)\nDescription:  The currently proposed \"Scopes\" (stage 3) encoding.  Use unsigned VLQ where appropriate.\n\nName:         Prefix (Option A)\nDescription:  Prefix start/end items with their length\n\nName:         Prefix (Option A, unsigned)\nDescription:  Prefix start/end items with their length. Use unsigned VLQ where appropriate.\n\nName:         Remaining (Option B)\nDescription:  Add a \"remaining VLQs count\" to items for unknown flags\n\nName:         Remaining (Option B, unsigned)\nDescription:  Add a \"remaining VLQs count\" to items for unknown flags. Use unsigned VLQ where appropriate.\n\nName:         Tag-Value-Length Split (Option C)\nDescription:  Prefix start/end items with a tag and their length\n\nName:         Tag-Value-Length Split (Option C, unsigned)\nDescription:  Prefix start/end items with a tag and their length. Use unsigned VLQ where appropriate.\n\nName:         Tag-Value-Length Combined (Option D)\nDescription:  Prefix original/generated items with a tag and their length. Combine start/end items.\n\nName:         Tag-Value-Length Combined (Option D, unsigned)\nDescription:  Prefix original/generated items with a tag and their length. Combine start/end items. Use unsigned VLQ where appropriate.\n\nName:         Tag-Value-Length Variables (Option E)\nDescription:  Prefix original/generated items with a tag and their length. Combine start/end items. Separate items for variables/bindings.\n\nName:         Tag-Value-Length Variables (Option E, unsigned)\nDescription:  Prefix original/generated items with a tag and their length. Combine start/end items. Separate items for variables/bindings. Use unsigned VLQ where appropriate.\n\n┌───────┬────────────────────────────────────┬───────────────────────────────────────────────────┬───────────────────┬───────────┬────────────────────────┬───────────┬──────────────────────────┬───────────┐\n│ (idx) │ File                               │ Codec                                             │ Uncompressed size │ Δ raw     │ Compressed size (gzip) │ Δ gzip    │ Compressed size (brotli) │ Δ brotli  │\n├───────┼────────────────────────────────────┼───────────────────────────────────────────────────┼───────────────────┼───────────┼────────────────────────┼───────────┼──────────────────────────┼───────────┤\n│     0 │ \"./examples/simple.min.js.map\"     │                                                   │                   │           │                        │           │                          │           │\n│     1 │                                    │ \"Proposal\"                                        │ \"171\"             │ \"\"        │ \"137\"                  │ \"\"        │ \"105\"                    │ \"\"        │\n│     2 │                                    │ \"Proposal (unsigned)\"                             │ \"163\"             │ \"-4.68%\"  │ \"132\"                  │ \"-3.65%\"  │ \"101\"                    │ \"-3.81%\"  │\n│     3 │                                    │ \"Prefix (Option A)\"                               │ \"186\"             │ \"+8.77%\"  │ \"141\"                  │ \"+2.92%\"  │ \"115\"                    │ \"+9.52%\"  │\n│     4 │                                    │ \"Prefix (Option A, unsigned)\"                     │ \"182\"             │ \"+6.43%\"  │ \"137\"                  │ \"+0%\"     │ \"110\"                    │ \"+4.76%\"  │\n│     5 │                                    │ \"Remaining (Option B)\"                            │ \"162\"             │ \"-5.26%\"  │ \"130\"                  │ \"-5.11%\"  │ \"109\"                    │ \"+3.81%\"  │\n│     6 │                                    │ \"Remaining (Option B, unsigned)\"                  │ \"158\"             │ \"-7.6%\"   │ \"128\"                  │ \"-6.57%\"  │ \"100\"                    │ \"-4.76%\"  │\n│     7 │                                    │ \"Tag-Value-Length Split (Option C)\"               │ \"170\"             │ \"-0.58%\"  │ \"120\"                  │ \"-12.41%\" │ \"98\"                     │ \"-6.67%\"  │\n│     8 │                                    │ \"Tag-Value-Length Split (Option C, unsigned)\"     │ \"166\"             │ \"-2.92%\"  │ \"112\"                  │ \"-18.25%\" │ \"94\"                     │ \"-10.48%\" │\n│     9 │                                    │ \"Tag-Value-Length Combined (Option D)\"            │ \"158\"             │ \"-7.6%\"   │ \"114\"                  │ \"-16.79%\" │ \"94\"                     │ \"-10.48%\" │\n│    10 │                                    │ \"Tag-Value-Length Combined (Option D, unsigned)\"  │ \"154\"             │ \"-9.94%\"  │ \"109\"                  │ \"-20.44%\" │ \"96\"                     │ \"-8.57%\"  │\n│    11 │                                    │ \"Tag-Value-Length Variables (Option E)\"           │ \"178\"             │ \"+4.09%\"  │ \"121\"                  │ \"-11.68%\" │ \"101\"                    │ \"-3.81%\"  │\n│    12 │                                    │ \"Tag-Value-Length Variables (Option E, unsigned)\" │ \"174\"             │ \"+1.75%\"  │ \"115\"                  │ \"-16.06%\" │ \"96\"                     │ \"-8.57%\"  │\n│    13 │                                    │                                                   │                   │           │                        │           │                          │           │\n│    14 │ \"./examples/common.min.js.map\"     │                                                   │                   │           │                        │           │                          │           │\n│    15 │                                    │ \"Proposal\"                                        │ \"35,049\"          │ \"\"        │ \"10,510\"               │ \"\"        │ \"10,395\"                 │ \"\"        │\n│    16 │                                    │ \"Proposal (unsigned)\"                             │ \"34,100\"          │ \"-2.71%\"  │ \"10,396\"               │ \"-1.08%\"  │ \"10,252\"                 │ \"-1.38%\"  │\n│    17 │                                    │ \"Prefix (Option A)\"                               │ \"38,508\"          │ \"+9.87%\"  │ \"11,952\"               │ \"+13.72%\" │ \"11,573\"                 │ \"+11.33%\" │\n│    18 │                                    │ \"Prefix (Option A, unsigned)\"                     │ \"37,531\"          │ \"+7.08%\"  │ \"11,780\"               │ \"+12.08%\" │ \"11,399\"                 │ \"+9.66%\"  │\n│    19 │                                    │ \"Remaining (Option B)\"                            │ \"32,694\"          │ \"-6.72%\"  │ \"10,784\"               │ \"+2.61%\"  │ \"10,636\"                 │ \"+2.32%\"  │\n│    20 │                                    │ \"Remaining (Option B, unsigned)\"                  │ \"31,503\"          │ \"-10.12%\" │ \"10,528\"               │ \"+0.17%\"  │ \"10,389\"                 │ \"-0.06%\"  │\n│    21 │                                    │ \"Tag-Value-Length Split (Option C)\"               │ \"42,995\"          │ \"+22.67%\" │ \"12,311\"               │ \"+17.14%\" │ \"11,903\"                 │ \"+14.51%\" │\n│    22 │                                    │ \"Tag-Value-Length Split (Option C, unsigned)\"     │ \"41,586\"          │ \"+18.65%\" │ \"12,078\"               │ \"+14.92%\" │ \"11,645\"                 │ \"+12.03%\" │\n│    23 │                                    │ \"Tag-Value-Length Combined (Option D)\"            │ \"39,994\"          │ \"+14.11%\" │ \"11,733\"               │ \"+11.64%\" │ \"11,353\"                 │ \"+9.22%\"  │\n│    24 │                                    │ \"Tag-Value-Length Combined (Option D, unsigned)\"  │ \"38,572\"          │ \"+10.05%\" │ \"11,457\"               │ \"+9.01%\"  │ \"11,070\"                 │ \"+6.49%\"  │\n│    25 │                                    │ \"Tag-Value-Length Variables (Option E)\"           │ \"44,336\"          │ \"+26.5%\"  │ \"11,530\"               │ \"+9.71%\"  │ \"11,290\"                 │ \"+8.61%\"  │\n│    26 │                                    │ \"Tag-Value-Length Variables (Option E, unsigned)\" │ \"42,942\"          │ \"+22.52%\" │ \"11,264\"               │ \"+7.17%\"  │ \"11,064\"                 │ \"+6.44%\"  │\n│    27 │                                    │                                                   │                   │           │                        │           │                          │           │\n│    28 │ \"./examples/sdk.min.js.map\"        │                                                   │                   │           │                        │           │                          │           │\n│    29 │                                    │ \"Proposal\"                                        │ \"152,710\"         │ \"\"        │ \"47,908\"               │ \"\"        │ \"47,168\"                 │ \"\"        │\n│    30 │                                    │ \"Proposal (unsigned)\"                             │ \"148,431\"         │ \"-2.8%\"   │ \"47,500\"               │ \"-0.85%\"  │ \"46,716\"                 │ \"-0.96%\"  │\n│    31 │                                    │ \"Prefix (Option A)\"                               │ \"166,927\"         │ \"+9.31%\"  │ \"53,488\"               │ \"+11.65%\" │ \"51,981\"                 │ \"+10.2%\"  │\n│    32 │                                    │ \"Prefix (Option A, unsigned)\"                     │ \"163,270\"         │ \"+6.92%\"  │ \"52,961\"               │ \"+10.55%\" │ \"51,441\"                 │ \"+9.06%\"  │\n│    33 │                                    │ \"Remaining (Option B)\"                            │ \"142,512\"         │ \"-6.68%\"  │ \"49,024\"               │ \"+2.33%\"  │ \"48,503\"                 │ \"+2.83%\"  │\n│    34 │                                    │ \"Remaining (Option B, unsigned)\"                  │ \"137,866\"         │ \"-9.72%\"  │ \"48,143\"               │ \"+0.49%\"  │ \"47,656\"                 │ \"+1.03%\"  │\n│    35 │                                    │ \"Tag-Value-Length Split (Option C)\"               │ \"185,950\"         │ \"+21.77%\" │ \"55,295\"               │ \"+15.42%\" │ \"53,486\"                 │ \"+13.39%\" │\n│    36 │                                    │ \"Tag-Value-Length Split (Option C, unsigned)\"     │ \"180,805\"         │ \"+18.4%\"  │ \"54,612\"               │ \"+13.99%\" │ \"52,575\"                 │ \"+11.46%\" │\n│    37 │                                    │ \"Tag-Value-Length Combined (Option D)\"            │ \"173,278\"         │ \"+13.47%\" │ \"52,861\"               │ \"+10.34%\" │ \"51,504\"                 │ \"+9.19%\"  │\n│    38 │                                    │ \"Tag-Value-Length Combined (Option D, unsigned)\"  │ \"168,096\"         │ \"+10.08%\" │ \"51,945\"               │ \"+8.43%\"  │ \"50,602\"                 │ \"+7.28%\"  │\n│    39 │                                    │ \"Tag-Value-Length Variables (Option E)\"           │ \"190,899\"         │ \"+25.01%\" │ \"52,052\"               │ \"+8.65%\"  │ \"51,128\"                 │ \"+8.4%\"   │\n│    40 │                                    │ \"Tag-Value-Length Variables (Option E, unsigned)\" │ \"185,785\"         │ \"+21.66%\" │ \"51,223\"               │ \"+6.92%\"  │ \"50,367\"                 │ \"+6.78%\"  │\n│    41 │                                    │                                                   │                   │           │                        │           │                          │           │\n│    42 │ \"./examples/typescript.min.js.map\" │                                                   │                   │           │                        │           │                          │           │\n│    43 │                                    │ \"Proposal\"                                        │ \"1,226,318\"       │ \"\"        │ \"427,409\"              │ \"\"        │ \"403,839\"                │ \"\"        │\n│    44 │                                    │ \"Proposal (unsigned)\"                             │ \"1,199,731\"       │ \"-2.17%\"  │ \"425,627\"              │ \"-0.42%\"  │ \"401,488\"                │ \"-0.58%\"  │\n│    45 │                                    │ \"Prefix (Option A)\"                               │ \"1,326,946\"       │ \"+8.21%\"  │ \"476,402\"              │ \"+11.46%\" │ \"442,755\"                │ \"+9.64%\"  │\n│    46 │                                    │ \"Prefix (Option A, unsigned)\"                     │ \"1,296,273\"       │ \"+5.7%\"   │ \"471,876\"              │ \"+10.4%\"  │ \"434,358\"                │ \"+7.56%\"  │\n│    47 │                                    │ \"Remaining (Option B)\"                            │ \"1,162,783\"       │ \"-5.18%\"  │ \"437,372\"              │ \"+2.33%\"  │ \"415,149\"                │ \"+2.8%\"   │\n│    48 │                                    │ \"Remaining (Option B, unsigned)\"                  │ \"1,117,642\"       │ \"-8.86%\"  │ \"431,507\"              │ \"+0.96%\"  │ \"404,017\"                │ \"+0.04%\"  │\n│    49 │                                    │ \"Tag-Value-Length Split (Option C)\"               │ \"1,460,672\"       │ \"+19.11%\" │ \"490,192\"              │ \"+14.69%\" │ \"454,869\"                │ \"+12.64%\" │\n│    50 │                                    │ \"Tag-Value-Length Split (Option C, unsigned)\"     │ \"1,419,447\"       │ \"+15.75%\" │ \"484,204\"              │ \"+13.29%\" │ \"444,055\"                │ \"+9.96%\"  │\n│    51 │                                    │ \"Tag-Value-Length Combined (Option D)\"            │ \"1,371,961\"       │ \"+11.88%\" │ \"476,015\"              │ \"+11.37%\" │ \"444,253\"                │ \"+10.01%\" │\n│    52 │                                    │ \"Tag-Value-Length Combined (Option D, unsigned)\"  │ \"1,330,208\"       │ \"+8.47%\"  │ \"469,904\"              │ \"+9.94%\"  │ \"433,458\"                │ \"+7.33%\"  │\n│    53 │                                    │ \"Tag-Value-Length Variables (Option E)\"           │ \"1,456,763\"       │ \"+18.79%\" │ \"466,693\"              │ \"+9.19%\"  │ \"438,060\"                │ \"+8.47%\"  │\n│    54 │                                    │ \"Tag-Value-Length Variables (Option E, unsigned)\" │ \"1,416,025\"       │ \"+15.47%\" │ \"458,821\"              │ \"+7.35%\"  │ \"428,188\"                │ \"+6.03%\"  │\n│    55 │                                    │                                                   │                   │           │                        │           │                          │           │\n└───────┴────────────────────────────────────┴───────────────────────────────────────────────────┴───────────────────┴───────────┴────────────────────────┴───────────┴──────────────────────────┴───────────┘\n```\n\n## Goal: future-proofing \"Scopes\"\n\nThe current \"Scopes\" encoding is not ideal w.r.t. to future extension:\n\n- Adding new fields to `OriginalScope` and `GeneratedRange` in a backwards\n  compatible way is impossible. Any tool implementing the current proposal would\n  break once we add new optional fields to either data structure.\n\n- The encoding uses the `,` and `;` characters on top of base64 encoded VLQ\n  numbers. Moving to a future binary source map format will require a different\n  encoding for \"Scopes\" to account for `,` and `;`.\n\nWe should aim for an encoding that is both forwards-compatible and is purely VLQ\nbased: So the only difference between the current JSON source map format and a\npotential future binary format is how VLQs are encoded.\n\nThe crux of the issue is to find the right balance between\n\n- retaining some flexibility for future extensions without going overboard (e.g\n  DWARF-style encoding),\n- encoding/decoding complexity,\n- and encoded size.\n\nThis repository proposes some potential \"Scopes\" encodings that keep both goals\nin mind while aiming for a healthy balance.\n\n## Grammar\n\nThe encoding formats are presented in a EBNF-like grammar with:\n\n- there is only one terminal: a VLQ. Each terminal is labelled and we denote\n  them with uppercase (e.g. `TERMINAL` is a VLQ with the label 'TERMINAL').\n- non-terminals denoted with snake case (e.g. `non_term`).\n- `symbol*` means zero or more repetitions of `symbol`.\n- `symbol?` means zero or one `symbol`.\n- `symbol[N]` means N occurrences of `symbol`.\n\n## Option A - Prefix items with their length\n\n```\noriginal_scopes = (LENGTH original_item)*\n\noriginal_item = original_start_item | original_end_item\n\noriginal_start_item =\n    LINE\n    COLUMN\n    FLAGS\n    NAME? // present if FLAGS\u003c0\u003e is set\n    KIND? // present if FLAGS\u003c1\u003e is set\n    VARIABLE_COUNT\n    VARIABLE[VARIABLE_COUNT]\n\noriginal_end_item =\n    LINE\n    COLUMN\n\ngenerated_ranges = (LENGTH generated_item)*\n\ngenerated_item = generated_start_item | generated_end_item\n\ngenerated_start_item =\n    COLUMN   // the actual value is COLUMN\u003c1:n\u003e.\n    LINE?    // if COLUMN\u003c0\u003e is set.\n    FLAGS\n    DEFINITION_SOURCE_OFFSET?  // present if FLAGS\u003c0\u003e is set\n    DEFINITION_ITEM_OFFSET?    // present if FLAGS\u003c0\u003e is set\n    CALL_SITE_SOURCE?          // present if FLAGS\u003c1\u003e is set\n    CALL_SITE_LINE?            // present if FLAGS\u003c1\u003e is set\n    CALL_SITE_COLUMN?          // present if FLAGS\u003c1\u003e is set\n    BINDING_COUNT\n    binding[BINDING_COUNT]\n\nbinding =\n    EXPR_OR_SUB_RANGE_LENGTH   // -1 = not available, \u003e=0 offset into \"names\"\n    EXPR_0?                    // present if EXPR_OR_SUBRANGE_LENGTH \u003c -1.\n    sub_range_binding[-EXPR_OR_SUBRANGE_LENGTH - 1]\n\nsub_range_binding =\n    LINE\n    COLUMN\n    EXPR\n\ngenerated_end_item =\n    COLUMN   // the actual value is COLUMN\u003c1:n\u003e.\n    LINE?    // if COLUMN\u003c0\u003e is set.\n```\n\nThis is identical to the current proposal modulo:\n\n- Each item is prefixed with the number of VLQs in the item\n- Variables in `OriginalScope` and bindings in `GeneratedRange` are prefixed\n  with their length\n- columns in the generated range encode whether a line VLQ is present or not\n\n`original_start_item` and `original_end_item` are distinguished by their length:\nA \"end\" item always has 2 VLQs while a \"start\" item has at least 3.\n`generated_start_item` and `generated_end_item` are distinguished by their\nlength: A \"end\" item has 1 or 2 VLQs while a \"start\" item has at least 3.\n\n## Option B - Add \"remaining\" count in the presence of unknown flags\n\nTo distinguish start/end items, we have to use an additional bit. For\n`original_*_item` we use a bit in `LINE` while for `generated_*_item` we use\nanother bit in `COLUMN`.\n\nWe'll list only the changed productions w.r.t. to \"Option A\":\n\n```\noriginal_scopes = original_item*\n\noriginal_start_item =\n    LINE  // the actual value is LINE\u003c1:n\u003e. LINE\u003c0\u003e is always 0 for original_start_item.\n    COLUMN\n    FLAGS\n    NAME? // present if FLAGS\u003c0\u003e is set\n    KIND? // present if FLAGS\u003c1\u003e is set\n    VARIABLE_COUNT\n    VARIABLE[VARIABLE_COUNT]\n    REMAINING?  // present if FLAGS\u003cn:3\u003e is not zero.\n    REST[REMAINING]\n\noriginal_end_item =\n    LINE // the actual value is LINE\u003c1:n\u003e. LINE\u003c0\u003e is always 1 for original_end_item.\n    COLUMN\n\ngenerated_ranges = generated_item*\n\ngenerated_start_item =\n    COLUMN   // the actual value is COLUMN\u003c2:n\u003e. COLUMN\u003c1\u003e is always 0 for generated_start_item.\n    LINE?    // if COLUMN\u003c0\u003e is set.\n    FLAGS\n    DEFINITION_SOURCE_OFFSET?  // present if FLAGS\u003c0\u003e is set\n    DEFINITION_ITEM_OFFSET?    // present if FLAGS\u003c0\u003e is set\n    CALL_SITE_SOURCE?          // present if FLAGS\u003c1\u003e is set\n    CALL_SITE_LINE?            // present if FLAGS\u003c1\u003e is set\n    CALL_SITE_COLUMN?          // present if FLAGS\u003c1\u003e is set\n    BINDING_COUNT\n    binding[BINDING_COUNT]\n    REMAINING?  // present if FLAGS\u003cn:4\u003e is not zero.\n    REST[REMAINING]\n\ngenerated_end_item =\n    COLUMN   // the actual value is COLUMN\u003c2:n\u003e. COLUMN\u003c1\u003e is always 1 for generated_end_item.\n    LINE?    // if COLUMN\u003c0\u003e is set.\n```\n\nAdvantages over Option A:\n\n- We only pay the price of encoding the item length once we actually add new\n  fields\n- Variables/bindings are not included, so REMAINING stays small even for\n  scopes/ranges with lots of variables\n\nQuirks:\n\n- Adding new marker flags to FLAGS (not new fields) requires generators to emit\n  a `REMAINING` value of 0.\n\n## Option C - Tag-Length-Value Split\n\nSimilar to Option A but we prefix each item not only with it's length but a tag\nas well. The advantages are:\n\n- We can encode scopes and ranges in one blob. That is the JSON could have a\n  single \"scopes\" field containing the combination of \"originalScopes\" and\n  \"generatedRanges\".\n- Start/end items can be distinguished by their tag.\n- We keep the door open for not only extending `original_start_item` and\n  `generated_start_item`, but adding new item types all-together.\n- `GeneratedRange.definition` only requires one index instead of two.\n\nSince it's similar to option A, we'll list only the changed productions:\n\n```\nscopes = items*\n\nitem =\n      \"0x1\" LENGTH original_start_item\n    | \"0x2\" LENGTH original_end_item\n    | \"0x3\" LENGTH generated_start_item\n    | \"0x4\" LENGTH generated_end_item\n\ngenerated_start_item =\n    COLUMN   // the actual value is COLUMN\u003c1:n\u003e.\n    LINE?    // if COLUMN\u003c0\u003e is set.\n    FLAGS\n    DEFINITION_ITEM_OFFSET?    // present if FLAGS\u003c0\u003e is set\n    CALL_SITE_SOURCE?          // present if FLAGS\u003c1\u003e is set\n    CALL_SITE_LINE?            // present if FLAGS\u003c1\u003e is set\n    CALL_SITE_COLUMN?          // present if FLAGS\u003c1\u003e is set\n    BINDING_COUNT\n    binding[BINDING_COUNT]\n    REMAINING?  // present if FLAGS\u003cn:4\u003e is not zero.\n    REST[REMAINING]\n```\n\n## Option D - Tag-Length-Value Combined\n\nThis is a variant to Option C. Instead of using `original_start_item` and\n`original_end_item`, we combine both into a `original_item`. Similar to DWARF,\nnesting is achieved by using a special tag to denote the end of an item's\nchildren.\n\n```\nitem =\n      \"0x0\"\n    | \"0x1\" LENGTH original_item\n    | \"0x2\" LENGTH generated_item\n\noriginal_item =\n    START_LINE\n    START_COLUMN\n    END_LINE\n    END_COLUMN\n    FLAGS\n    // ...\n\ngenerated_item =\n    START_COLUMN   // the actual value is START_COLUMN\u003c1:n\u003e.\n    START_LINE?    // present if START_COLUMN\u003c0\u003e is set.\n    END_COLUMN     // the actual value is END_COLUMN\u003c1:n\u003e.\n    END_LINE?      // present if END_COLUMN\u003c0\u003e is set.\n    FLAGS\n    // ....\n```\n\nExample of nested scopes (tags only):\n`[0x1, ...\u003clength + content\u003e, 0x1, ...\u003clength + content\u003e, 0x0, 0x0]`.\n\nThis comes with some special rules if we don't want to lose the efficiency of\nrelative line/column numbers for start and end locations:\n\n- A scopes or ranges' start location is relative to the preceding siblings' end\n  location, or the parents' start location if it's the first child.\n- A scopes or ranges' end location is relative to it's last child's end\n  location, or it's start location if it does not have any children.\n\nThere is also the question of `START_LINE`, and `END_LINE` in `generated_item`.\nWe could encode it's presence in FLAGS or use the LSB of the respective\n`*_COLUMN`.\n\n## Option E - Tag-Length-Value Variables\n\nThis is a variant of Option D: Instead of including variables and bindings in\n`original_item` and `generated_item` respectively, we encode them in separate\n`variable` and `binding` items.\n\n```\nitem =\n      \"0x0\"\n    | \"0x1\" LENGTH original_item\n    | \"0x2\" LENGTH generated_item\n    | \"0x3\" LENGTH variables\n    | \"0x4\" LENGTH bindings\n\noriginal_item =\n    START_LINE\n    START_COLUMN\n    END_LINE\n    END_COLUMN\n    FLAGS\n    NAME? // present if FLAGS\u003c0\u003e is set\n    KIND? // present if FLAGS\u003c1\u003e is set\n\nvariables =\n    VARIABLE_COUNT\n    VARIABLE[VARIABLE_COUNT]\n\ngenerated_item =\n    START_COLUMN   // the actual value is START_COLUMN\u003c1:n\u003e.\n    START_LINE?    // present if START_COLUMN\u003c0\u003e is set.\n    END_COLUMN     // the actual value is END_COLUMN\u003c1:n\u003e.\n    END_LINE?      // present if END_COLUMN\u003c0\u003e is set.\n    FLAGS\n    DEFINITION_ITEM_OFFSET?    // present if FLAGS\u003c0\u003e is set\n    CALL_SITE_SOURCE?          // present if FLAGS\u003c1\u003e is set\n    CALL_SITE_LINE?            // present if FLAGS\u003c1\u003e is set\n    CALL_SITE_COLUMN?          // present if FLAGS\u003c1\u003e is set\n\nbindings =\n    BINDING_COUNT\n    binding[BINDING_COUNT]\n```\n\nNote that `variables` and `bindings` can't have child items. Nonetheless some\ntools may chose to add child items so it is required that generators \"close\"\n`variables` and `bindings` with an `EMPTY` tag.\n\nThis could be improved by using the first bit of the tag to signal whether a tag\nhas child items or not.\n\n## Unsigned VLQ\n\nThe current source map specification only allows for signed VLQ. This makes\nsense for mappings where most fields are relative. The \"Scopes\" proposal\nincludes various fields that can never be negative. As such it could be\ninteresting to see the impact on the encoding scheme if unsigned VLQs are\nallowed.\n\nThe tool includes support for unsigned VLQ and will output the result for each\nencoding scheme for both signed VLQ only, as well as using unsigned VLQ where\npossible.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchromedevtools%2Fsourcemap-scopes-encoding","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchromedevtools%2Fsourcemap-scopes-encoding","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchromedevtools%2Fsourcemap-scopes-encoding/lists"}