diff --git a/.github/workflows/auto-publish.yml b/.github/workflows/auto-publish.yml new file mode 100644 index 0000000..c2fd3aa --- /dev/null +++ b/.github/workflows/auto-publish.yml @@ -0,0 +1,17 @@ +name: CI +on: + pull_request: {} + push: + branches: [main] +jobs: + main: + name: Build, Validate and Deploy + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v3 + - uses: w3c/spec-prod@v2 + with: + GH_PAGES_BRANCH: gh-pages + TOOLCHAIN: bikeshed + SOURCE: source-map.bs + DESTINATION: index.html diff --git a/.github/workflows/ipr.yml b/.github/workflows/ipr.yml new file mode 100644 index 0000000..b877828 --- /dev/null +++ b/.github/workflows/ipr.yml @@ -0,0 +1,22 @@ +name: 'ecma-262' + +on: + pull_request_target: + branches: + - '*' + push: + branches: + - main + +jobs: + build: + name: 'check IPR form' + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + - run: node scripts/ipr-check.js tc39/source-map-spec ${{ github.event.pull_request.head.sha || 'HEAD' }} + env: + GH_TOKEN: ${{ secrets.GH_IPR_TOKEN }} + GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1468841 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.venv +source-map.html +.env diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..dc079b4 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,93 @@ +# Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of +experience, education, socio-economic status, nationality, personal appearance, +race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, or to ban temporarily or permanently any +contributor for other behaviors that they deem inappropriate, threatening, +offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +This Code of Conduct also applies outside the project spaces when the Project +Steward has a reasonable belief that an individual's behavior may have a +negative impact on the project or its community. + +## Conflict Resolution + +We do not believe that all conflict is bad; healthy debate and disagreement +often yield positive results. However, it is never okay to be disrespectful or +to engage in behavior that violates the project’s code of conduct. + +If you see someone violating the code of conduct, you are encouraged to address +the behavior directly with those involved. Many issues can be resolved quickly +and easily, and this gives people more control over the outcome of their +dispute. If you are unable to resolve the matter for any reason, or if the +behavior is threatening or harassing, report it. We are dedicated to providing +an environment where participants feel welcome and safe. + +Reports should be directed to *[PROJECT STEWARD NAME(s) AND EMAIL(s)]*, the +Project Steward(s) for *[PROJECT NAME]*. It is the Project Steward’s duty to +receive and address reported violations of the code of conduct. They will then +work with a committee consisting of representatives from the Open Source +Programs Office and the Google Open Source Strategy team. If for any reason you +are uncomfortable reaching out to the Project Steward, please email +opensource@google.com. + +We will investigate every complaint, but you may not receive a direct response. +We will use our discretion in determining when and how to follow up on reported +incidents, which may range from not taking action to permanent expulsion from +the project and project-sponsored spaces. We will notify the accused of the +report and provide them an opportunity to discuss it before any action is taken. +The identity of the reporter will be omitted from the details of the report +supplied to the accused. In potentially harmful situations, such as ongoing +harassment or threats to anyone's safety, we may take action without notice. + +## Attribution + +This Code of Conduct is adapted from the Contributor Covenant, version 1.4, +available at +https://www.contributor-covenant.org/version/1/4/code-of-conduct.html diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..604209a --- /dev/null +++ b/LICENSE @@ -0,0 +1,359 @@ +Creative Commons Legal Code + +Attribution-ShareAlike 3.0 Unported + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR + DAMAGES RESULTING FROM ITS USE. + +License + +THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE +COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY +COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS +AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. + +BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE +TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY +BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS +CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND +CONDITIONS. + +1. Definitions + + a. "Adaptation" means a work based upon the Work, or upon the Work and + other pre-existing works, such as a translation, adaptation, + derivative work, arrangement of music or other alterations of a + literary or artistic work, or phonogram or performance and includes + cinematographic adaptations or any other form in which the Work may be + recast, transformed, or adapted including in any form recognizably + derived from the original, except that a work that constitutes a + Collection will not be considered an Adaptation for the purpose of + this License. For the avoidance of doubt, where the Work is a musical + work, performance or phonogram, the synchronization of the Work in + timed-relation with a moving image ("synching") will be considered an + Adaptation for the purpose of this License. + b. "Collection" means a collection of literary or artistic works, such as + encyclopedias and anthologies, or performances, phonograms or + broadcasts, or other works or subject matter other than works listed + in Section 1(f) below, which, by reason of the selection and + arrangement of their contents, constitute intellectual creations, in + which the Work is included in its entirety in unmodified form along + with one or more other contributions, each constituting separate and + independent works in themselves, which together are assembled into a + collective whole. A work that constitutes a Collection will not be + considered an Adaptation (as defined below) for the purposes of this + License. + c. "Creative Commons Compatible License" means a license that is listed + at https://creativecommons.org/compatiblelicenses that has been + approved by Creative Commons as being essentially equivalent to this + License, including, at a minimum, because that license: (i) contains + terms that have the same purpose, meaning and effect as the License + Elements of this License; and, (ii) explicitly permits the relicensing + of adaptations of works made available under that license under this + License or a Creative Commons jurisdiction license with the same + License Elements as this License. + d. "Distribute" means to make available to the public the original and + copies of the Work or Adaptation, as appropriate, through sale or + other transfer of ownership. + e. "License Elements" means the following high-level license attributes + as selected by Licensor and indicated in the title of this License: + Attribution, ShareAlike. + f. "Licensor" means the individual, individuals, entity or entities that + offer(s) the Work under the terms of this License. + g. "Original Author" means, in the case of a literary or artistic work, + the individual, individuals, entity or entities who created the Work + or if no individual or entity can be identified, the publisher; and in + addition (i) in the case of a performance the actors, singers, + musicians, dancers, and other persons who act, sing, deliver, declaim, + play in, interpret or otherwise perform literary or artistic works or + expressions of folklore; (ii) in the case of a phonogram the producer + being the person or legal entity who first fixes the sounds of a + performance or other sounds; and, (iii) in the case of broadcasts, the + organization that transmits the broadcast. + h. "Work" means the literary and/or artistic work offered under the terms + of this License including without limitation any production in the + literary, scientific and artistic domain, whatever may be the mode or + form of its expression including digital form, such as a book, + pamphlet and other writing; a lecture, address, sermon or other work + of the same nature; a dramatic or dramatico-musical work; a + choreographic work or entertainment in dumb show; a musical + composition with or without words; a cinematographic work to which are + assimilated works expressed by a process analogous to cinematography; + a work of drawing, painting, architecture, sculpture, engraving or + lithography; a photographic work to which are assimilated works + expressed by a process analogous to photography; a work of applied + art; an illustration, map, plan, sketch or three-dimensional work + relative to geography, topography, architecture or science; a + performance; a broadcast; a phonogram; a compilation of data to the + extent it is protected as a copyrightable work; or a work performed by + a variety or circus performer to the extent it is not otherwise + considered a literary or artistic work. + i. "You" means an individual or entity exercising rights under this + License who has not previously violated the terms of this License with + respect to the Work, or who has received express permission from the + Licensor to exercise rights under this License despite a previous + violation. + j. "Publicly Perform" means to perform public recitations of the Work and + to communicate to the public those public recitations, by any means or + process, including by wire or wireless means or public digital + performances; to make available to the public Works in such a way that + members of the public may access these Works from a place and at a + place individually chosen by them; to perform the Work to the public + by any means or process and the communication to the public of the + performances of the Work, including by public digital performance; to + broadcast and rebroadcast the Work by any means including signs, + sounds or images. + k. "Reproduce" means to make copies of the Work by any means including + without limitation by sound or visual recordings and the right of + fixation and reproducing fixations of the Work, including storage of a + protected performance or phonogram in digital form or other electronic + medium. + +2. Fair Dealing Rights. Nothing in this License is intended to reduce, +limit, or restrict any uses free from copyright or rights arising from +limitations or exceptions that are provided for in connection with the +copyright protection under copyright law or other applicable laws. + +3. License Grant. Subject to the terms and conditions of this License, +Licensor hereby grants You a worldwide, royalty-free, non-exclusive, +perpetual (for the duration of the applicable copyright) license to +exercise the rights in the Work as stated below: + + a. to Reproduce the Work, to incorporate the Work into one or more + Collections, and to Reproduce the Work as incorporated in the + Collections; + b. to create and Reproduce Adaptations provided that any such Adaptation, + including any translation in any medium, takes reasonable steps to + clearly label, demarcate or otherwise identify that changes were made + to the original Work. For example, a translation could be marked "The + original work was translated from English to Spanish," or a + modification could indicate "The original work has been modified."; + c. to Distribute and Publicly Perform the Work including as incorporated + in Collections; and, + d. to Distribute and Publicly Perform Adaptations. + e. For the avoidance of doubt: + + i. Non-waivable Compulsory License Schemes. In those jurisdictions in + which the right to collect royalties through any statutory or + compulsory licensing scheme cannot be waived, the Licensor + reserves the exclusive right to collect such royalties for any + exercise by You of the rights granted under this License; + ii. Waivable Compulsory License Schemes. In those jurisdictions in + which the right to collect royalties through any statutory or + compulsory licensing scheme can be waived, the Licensor waives the + exclusive right to collect such royalties for any exercise by You + of the rights granted under this License; and, + iii. Voluntary License Schemes. The Licensor waives the right to + collect royalties, whether individually or, in the event that the + Licensor is a member of a collecting society that administers + voluntary licensing schemes, via that society, from any exercise + by You of the rights granted under this License. + +The above rights may be exercised in all media and formats whether now +known or hereafter devised. The above rights include the right to make +such modifications as are technically necessary to exercise the rights in +other media and formats. Subject to Section 8(f), all rights not expressly +granted by Licensor are hereby reserved. + +4. Restrictions. The license granted in Section 3 above is expressly made +subject to and limited by the following restrictions: + + a. You may Distribute or Publicly Perform the Work only under the terms + of this License. You must include a copy of, or the Uniform Resource + Identifier (URI) for, this License with every copy of the Work You + Distribute or Publicly Perform. You may not offer or impose any terms + on the Work that restrict the terms of this License or the ability of + the recipient of the Work to exercise the rights granted to that + recipient under the terms of the License. You may not sublicense the + Work. You must keep intact all notices that refer to this License and + to the disclaimer of warranties with every copy of the Work You + Distribute or Publicly Perform. When You Distribute or Publicly + Perform the Work, You may not impose any effective technological + measures on the Work that restrict the ability of a recipient of the + Work from You to exercise the rights granted to that recipient under + the terms of the License. This Section 4(a) applies to the Work as + incorporated in a Collection, but this does not require the Collection + apart from the Work itself to be made subject to the terms of this + License. If You create a Collection, upon notice from any Licensor You + must, to the extent practicable, remove from the Collection any credit + as required by Section 4(c), as requested. If You create an + Adaptation, upon notice from any Licensor You must, to the extent + practicable, remove from the Adaptation any credit as required by + Section 4(c), as requested. + b. You may Distribute or Publicly Perform an Adaptation only under the + terms of: (i) this License; (ii) a later version of this License with + the same License Elements as this License; (iii) a Creative Commons + jurisdiction license (either this or a later license version) that + contains the same License Elements as this License (e.g., + Attribution-ShareAlike 3.0 US)); (iv) a Creative Commons Compatible + License. If you license the Adaptation under one of the licenses + mentioned in (iv), you must comply with the terms of that license. If + you license the Adaptation under the terms of any of the licenses + mentioned in (i), (ii) or (iii) (the "Applicable License"), you must + comply with the terms of the Applicable License generally and the + following provisions: (I) You must include a copy of, or the URI for, + the Applicable License with every copy of each Adaptation You + Distribute or Publicly Perform; (II) You may not offer or impose any + terms on the Adaptation that restrict the terms of the Applicable + License or the ability of the recipient of the Adaptation to exercise + the rights granted to that recipient under the terms of the Applicable + License; (III) You must keep intact all notices that refer to the + Applicable License and to the disclaimer of warranties with every copy + of the Work as included in the Adaptation You Distribute or Publicly + Perform; (IV) when You Distribute or Publicly Perform the Adaptation, + You may not impose any effective technological measures on the + Adaptation that restrict the ability of a recipient of the Adaptation + from You to exercise the rights granted to that recipient under the + terms of the Applicable License. This Section 4(b) applies to the + Adaptation as incorporated in a Collection, but this does not require + the Collection apart from the Adaptation itself to be made subject to + the terms of the Applicable License. + c. If You Distribute, or Publicly Perform the Work or any Adaptations or + Collections, You must, unless a request has been made pursuant to + Section 4(a), keep intact all copyright notices for the Work and + provide, reasonable to the medium or means You are utilizing: (i) the + name of the Original Author (or pseudonym, if applicable) if supplied, + and/or if the Original Author and/or Licensor designate another party + or parties (e.g., a sponsor institute, publishing entity, journal) for + attribution ("Attribution Parties") in Licensor's copyright notice, + terms of service or by other reasonable means, the name of such party + or parties; (ii) the title of the Work if supplied; (iii) to the + extent reasonably practicable, the URI, if any, that Licensor + specifies to be associated with the Work, unless such URI does not + refer to the copyright notice or licensing information for the Work; + and (iv) , consistent with Ssection 3(b), in the case of an + Adaptation, a credit identifying the use of the Work in the Adaptation + (e.g., "French translation of the Work by Original Author," or + "Screenplay based on original Work by Original Author"). The credit + required by this Section 4(c) may be implemented in any reasonable + manner; provided, however, that in the case of a Adaptation or + Collection, at a minimum such credit will appear, if a credit for all + contributing authors of the Adaptation or Collection appears, then as + part of these credits and in a manner at least as prominent as the + credits for the other contributing authors. For the avoidance of + doubt, You may only use the credit required by this Section for the + purpose of attribution in the manner set out above and, by exercising + Your rights under this License, You may not implicitly or explicitly + assert or imply any connection with, sponsorship or endorsement by the + Original Author, Licensor and/or Attribution Parties, as appropriate, + of You or Your use of the Work, without the separate, express prior + written permission of the Original Author, Licensor and/or Attribution + Parties. + d. Except as otherwise agreed in writing by the Licensor or as may be + otherwise permitted by applicable law, if You Reproduce, Distribute or + Publicly Perform the Work either by itself or as part of any + Adaptations or Collections, You must not distort, mutilate, modify or + take other derogatory action in relation to the Work which would be + prejudicial to the Original Author's honor or reputation. Licensor + agrees that in those jurisdictions (e.g. Japan), in which any exercise + of the right granted in Section 3(b) of this License (the right to + make Adaptations) would be deemed to be a distortion, mutilation, + modification or other derogatory action prejudicial to the Original + Author's honor and reputation, the Licensor will waive or not assert, + as appropriate, this Section, to the fullest extent permitted by the + applicable national law, to enable You to reasonably exercise Your + right under Section 3(b) of this License (right to make Adaptations) + but not otherwise. + +5. Representations, Warranties and Disclaimer + +UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR +OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY +KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, +INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, +FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF +LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, +WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION +OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU. + +6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE +LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR +ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES +ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +7. Termination + + a. This License and the rights granted hereunder will terminate + automatically upon any breach by You of the terms of this License. + Individuals or entities who have received Adaptations or Collections + from You under this License, however, will not have their licenses + terminated provided such individuals or entities remain in full + compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will + survive any termination of this License. + b. Subject to the above terms and conditions, the license granted here is + perpetual (for the duration of the applicable copyright in the Work). + Notwithstanding the above, Licensor reserves the right to release the + Work under different license terms or to stop distributing the Work at + any time; provided, however that any such election will not serve to + withdraw this License (or any other license that has been, or is + required to be, granted under the terms of this License), and this + License will continue in full force and effect unless terminated as + stated above. + +8. Miscellaneous + + a. Each time You Distribute or Publicly Perform the Work or a Collection, + the Licensor offers to the recipient a license to the Work on the same + terms and conditions as the license granted to You under this License. + b. Each time You Distribute or Publicly Perform an Adaptation, Licensor + offers to the recipient a license to the original Work on the same + terms and conditions as the license granted to You under this License. + c. If any provision of this License is invalid or unenforceable under + applicable law, it shall not affect the validity or enforceability of + the remainder of the terms of this License, and without further action + by the parties to this agreement, such provision shall be reformed to + the minimum extent necessary to make such provision valid and + enforceable. + d. No term or provision of this License shall be deemed waived and no + breach consented to unless such waiver or consent shall be in writing + and signed by the party to be charged with such waiver or consent. + e. This License constitutes the entire agreement between the parties with + respect to the Work licensed here. There are no understandings, + agreements or representations with respect to the Work not specified + here. Licensor shall not be bound by any additional provisions that + may appear in any communication from You. This License may not be + modified without the mutual written agreement of the Licensor and You. + f. The rights granted under, and the subject matter referenced, in this + License were drafted utilizing the terminology of the Berne Convention + for the Protection of Literary and Artistic Works (as amended on + September 28, 1979), the Rome Convention of 1961, the WIPO Copyright + Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 + and the Universal Copyright Convention (as revised on July 24, 1971). + These rights and subject matter take effect in the relevant + jurisdiction in which the License terms are sought to be enforced + according to the corresponding provisions of the implementation of + those treaty provisions in the applicable national law. If the + standard suite of rights granted under applicable copyright law + includes additional rights not granted under this License, such + additional rights are deemed to be included in the License; this + License is not intended to restrict the license of any rights under + applicable law. + + +Creative Commons Notice + + Creative Commons is not a party to this License, and makes no warranty + whatsoever in connection with the Work. Creative Commons will not be + liable to You or any party on any legal theory for any damages + whatsoever, including without limitation any general, special, + incidental or consequential damages arising in connection to this + license. Notwithstanding the foregoing two (2) sentences, if Creative + Commons has expressly identified itself as the Licensor hereunder, it + shall have all rights and obligations of Licensor. + + Except for the limited purpose of indicating to the public that the + Work is licensed under the CCPL, Creative Commons does not authorize + the use by either party of the trademark "Creative Commons" or any + related trademark or logo of Creative Commons without the prior + written consent of Creative Commons. Any permitted use will be in + compliance with Creative Commons' then-current trademark usage + guidelines, as may be published on its website or otherwise made + available upon request from time to time. For the avoidance of doubt, + this trademark restriction does not form part of the License. + + Creative Commons may be contacted at https://creativecommons.org/. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..512ca13 --- /dev/null +++ b/Makefile @@ -0,0 +1,16 @@ +.PHONY: all +all: build + +.PHONY: build +build: .venv + .venv/bin/bikeshed spec + +.PHONY: watch +watch: .venv + .venv/bin/bikeshed watch + +.venv: + python3 -mvenv .venv + .venv/bin/pip install --upgrade pip + .venv/bin/pip install bikeshed + .venv/bin/bikeshed update diff --git a/README.md b/README.md new file mode 100644 index 0000000..181b28c --- /dev/null +++ b/README.md @@ -0,0 +1,39 @@ +# Source Map Specification + +![CC BY-SA 3.0](https://licensebuttons.net/l/by-sa/3.0/88x31.png) + +This repository contains the different revisions of the source map specification. + +The first and second revision of the spec are provided for historical context. +These revisions don't have widespread adoption in tools. + +## What's here + +The most recent specification is the v3 revision. It's converted into MarkDown +format for this repository. + +* [Revision 3](source-map-rev3.md) + +There is an ongoing initiative to harden the specification, clarify it and to +convert it into a stronger standard. The draft of this initiative can be found here: + +* [Draft Source](source-map.bs) +* [Rendered Draft](https://tc39.es/source-map-spec/) +* [RFC and Discussions](https://github.com/source-map/source-map-rfc/) + +Older revisions: + +* [Revision 2](source-map-rev2.md) +* [Revision 1](source-map-rev1.md) + +## License + +The source map specifications are published under CC BY-SA 3.0. + +## Original Locations + +These documents have previously been hosted on Google Docs: + +* Revision 1: [Source Mapping](https://docs.google.com/document/d/1g6tuP7unEkxUSZwLm4IcLoJn1eNDhEmZLAV2kphdvOY/edit) +* Revision 2: [Closure Compiler Source Map 2.0](https://docs.google.com/document/d/1xi12LrcqjqIHTtZzrzZKmQ3lbTv9mKrN076UB-j3UZQ/edit?hl=en_US) +* Revision 3: [Source Map Revision 3 Proposal](https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit#heading=h.1ce2c87bpj24) diff --git a/scripts/ipr-check.js b/scripts/ipr-check.js new file mode 100644 index 0000000..e4c5c75 --- /dev/null +++ b/scripts/ipr-check.js @@ -0,0 +1,181 @@ +#!/usr/bin/env node + +// Copied from https://github.com/tc39/ecma262/blob/c316ec72f6e227d88d4ef67a3e16b486c5ca356d/scripts/check-form.js, +// with some simplifications (we do not need to handle IPR for some legacy commits) +// - none of the current committers still need to sign the IPR form +// - none of the current committers use multiple GitHub accounts to commit to this repository + +const { execSync } = require('child_process'); + +// web URL: `https://docs.google.com/spreadsheets/d/${sheetID}/edit` +const sheetID = '1if5bU0aV5MJ27GGKnRzyAozeKP-ILXYl5r3dzvkGFmg'; + +const { + GOOGLE_API_KEY: key, // TC39 API key for google sheets + GH_TOKEN +} = process.env; + +if (!GH_TOKEN) { + throw 'GH_TOKEN env var required'; +} +if (!key) { + throw 'GOOGLE_API_KEY env var required'; +} + +const sheetData = `https://sheets.googleapis.com/v4/spreadsheets/${sheetID}/values/Sheet1!A2:A?key=${key}`; + +const [,, slug, branchOrSha] = process.argv; + +if (!slug || !branchOrSha) { + throw 'args required: slug, branchOrSha'; +} + +let sha = branchOrSha; +try { + sha = String(execSync(`git rev-parse --short ${branchOrSha}`)).trim(); +} catch {} + +console.log("Getting data for", sha); + +const request = async (url, method = 'GET', postData) => { + // adapted from https://medium.com/@gevorggalstyan/how-to-promisify-node-js-http-https-requests-76a5a58ed90c + const lib = url.startsWith('https://') ? require('https') : require('http'); + + const [h, path] = url.split('://')[1].split('/'); + const [host, port] = h.split(':'); + + const params = { + host, + port: port || url.startsWith('https://') ? 443 : 80, + method, + headers: { + Authorization: `token ${GH_TOKEN}`, + 'User-Agent': 'curl/7.54.0' + } + }; + + return new Promise((resolve, reject) => { + const req = lib.request(url, params, res => { + if (res.statusCode < 200 || res.statusCode >= 300) { + return reject(new Error(`Status Code: ${res.statusCode}; ${url}`)); + } + + const data = []; + + res.on('data', chunk => { + data.push(chunk); + }); + + res.on('end', () => resolve(String(Buffer.concat(data)))); + }); + + req.on('error', reject); + + if (postData) { + req.write(postData); + } + + req.end(); + }); +}; + +const perPage = 100; + +function getAuthorFromCommit(commitObj) { + if (!commitObj) { + return false; + } + const { author } = commitObj; + if (!author) { + throw new Error("Missing author for commit " + commitObj.sha); + } + return author.login; +} + +async function getAllCommits(page = 1) { + const commitsURL = `https://api.github.com/repos/${slug}/commits?anon=1&per_page=${perPage}&page=${page}&sha=${sha}`; + const commits = await request(commitsURL).then((json) => JSON.parse(json)); + return [...new Set([].concat( + commits.flatMap(x => getAuthorFromCommit(x) || []), + commits.length < perPage ? [] : await getAllCommits(page + 1), + ))]; +} + +const authors = getAllCommits().then((authors) => { + const knowns = authors.filter(x => typeof x === 'string'); + console.log(`Found ${knowns.length} authors: ${knowns.join(',')}\n`); + return knowns; +}); + +const teamURL = (team) => `https://api.github.com/orgs/tc39/teams/${team}`; + +function getMembers(teamID, page = 1) { + const memberURL = `https://api.github.com/teams/${teamID}/members?per_page=100&page=${page}`; + const data = request(memberURL).then((json) => JSON.parse(json)); + return data.then((data) => { + if (data.length === 0) { + return data; + } + return getMembers(teamID, page + 1).then(nextPage => { + return data.concat(nextPage); + }); + }); +} + +function handler(kind) { + return (data) => { + const names = new Set(data.map(x => x.login.toLowerCase())); + console.log(`Found ${names.size} ${kind}: ${[...names].join(',')}\n`); + return names; + } +} + +const delegates = request(teamURL('delegates')).then((json) => JSON.parse(json)).then(data => { + return getMembers(data.id); +}).then(handler('delegates')); + +const emeriti = request(teamURL('emeriti')).then((json) => JSON.parse(json)).then(data => { + return getMembers(data.id); +}).then(handler('emeriti')); + +const usernames = request(sheetData).then((json) => JSON.parse(json)).then(data => { + if (!Array.isArray(data.values)) { + throw 'invalid data'; + } + const usernames = new Set( + data.values + .flat(1) + .map(x => x.replace(/^(https?:\/\/)?github\.com\//, '').replace(/^@/, '').toLowerCase()) + .filter(x => /^[a-z0-9_-]{1,39}$/gi.test(x)) + .sort((a, b) => a.localeCompare(b)) + ); + console.log(`Found ${usernames.size} usernames: ` + [...usernames].join(',') + '\n'); + return usernames; +}); + +const exceptions = new Set([ + 'EricSL', // Google employee + 'jaro-sevcik', // Google empolyee + 'jkrems', // Google employee + 'josephschorr', // former Google empolyee + 'sideshowbarker', // Mozilla employee +].map(x => x.toLowerCase())); + +Promise.all([usernames, authors, delegates, emeriti]).then(([usernames, authors, delegates, emeriti]) => { + const missing = authors.filter(author => { + const a = author.toLowerCase(); + const signed = usernames.has(a) + || delegates.has(a) + || emeriti.has(a) + || exceptions.has(a); + return !signed; + }); + if (missing.length > 0) { + throw `Missing ${missing.length} authors: ${missing}`; + } else { + console.log('All authors have signed the form, or are delegates or emeriti!'); + } +}).catch((e) => { + console.error(e); + process.exitCode = 1; +}); diff --git a/source-map-rev1.md b/source-map-rev1.md new file mode 100644 index 0000000..1b80900 --- /dev/null +++ b/source-map-rev1.md @@ -0,0 +1,221 @@ +# Source Mapping + +### Background + +Many tools exist today which produce compressed or modified JavaScript as their output (examples: GWT, YUI minifier, Caja). Debugging the produced JavaScript is at best irritating and at worse nearly impossible, as these tools rename variables, move code and sometimes, radically alter the structure (but not the produced semantics) of the input JavaScript. Some tools (like GWT) even produce JavaScript from a different input language entirely, further frustrating the ability for developers to follow the sources of bugs in their programs. This document proposes a new technology entitled "source mapping" which will allow these tools to produce a logical code map which debuggers (such as LavaBug) can consume to provide better and more specific information to their users. + +### Overview + +The source mapping techonology consists of the production of source maps, files which follow a standardized format (defined below) and contain a mapping from the generated JavaScript source files to the original input file(s). These files can be produced by any tool, and consumed by any debugger, to map from some set of input language(s) to JavaScript. The file format is designed to be a) extensible, b) easy to produce and most importantly, c) fast to consume from within JavaScript. Point c is critical for the toolside (such as LavaBug) to be successful in using this technology. + +### Terminology and constructs + +Section - a set of data in the source map. All sections must begin with a declaration comment and must contain the number of lines that the section fills in the metadata object. These two items form the section header. Following the section header are a number of lines of text, whose format depends on the section. + + Example: + +``` +n: /\*\* some section. \*\*/ { 'count': 2 } + +n+1: any data can go here, + +n+2: including JS comments! /\*\* yay! \*\*/ +``` + +Section body - The body of a section consists of N number of lines of text, where N is the count found in the metadata object. For required sections, the format of this text is well defined. For custom sections (i.e. any others), the design is left to the implementing generator and debugger. + +Declaration comment - A comment declaring the beginning of a new section. Must start at character 0 on a line, and is always of the form: + +``` +/\*\* The section name/description goes here. \*\*/ +``` + +Declaration comments are always single line, and are always followed by the metadata object, on the same line. + +Metadata object - The metadata associated with a section is always found on the same line, right after the declaration comment. It consists of an object literal with a number of keys, of the form: + +``` +{ 'key1': 'data', 'key2': 3 } +``` + +Metadata objects are always single lined (which means all string must have newlines escaped to \\n), and always follow immediately after the declaration comment (i.e. no spaces between the comment and the object). + +Keys (case sensitive): + +* count - Integer - The number of lines that the section takes (not including the header). Required. +* All other keys MUST be namespaced + +Section header - The combination of the declaration comment and metadata object. Must be evaluated as JSON when the comment is removed (i.e. sending the string to an eval would result in the metadata object being returned). + +### Namespacing policy + +Unless otherwise noted, all custom keys, and sections, must be namespaced. Typically, this will be done by prefixing a namespace such as "com.google.thegenerator" to the key or section name. + + Example: `{ 'com.google.mygenerator.myflag': false }` + + Example: `/** com.google.mygenerator.customsection. **/` + +### Full Example + +(Text in _italics_ is solely for reference and not part of the actual file) + +_(1)_ /\*\* Begin source map. \*\*/ { 'version': 1 } + +_(2)_ /\*\* Begin file list. \*\*/ { 'count': 2 } + +\['input1.js', { 'ranges': \[10, 20, 30, 40\] }\] + +\['input2.js', { 'lang': 'java' } \] + +_(3)_/\*\* Begin character map. \*\*/ { 'count': 1 } + +\[0,,-1,,,2,,,3\] + +_(4)_/\*\* Begin mapping definitions. \*\*/ { 'count': 4 } + +\[0, 1, 10\] + +\[0, 2, 15\] + +\[0, 4, 67\] + +\[0, 6, 1\] + +\[1, 1, 0, { 'originalName': 'foobar' }\] + +_(5)_/\*\* Begin exception mappings. \*\*/ { 'count': 2, 'delimeter': '\\b' } + +\[2, "This is a message: %1", { 'com.google.whatever.metadata': 7 }\] + +\[3, "This is another message: %1"\] + +_(6)_/\*\* com\_google\_mygenerator\_customsection. \*\*/{'count': 1} + +My data can go here and I can put whatever I want! + +### Detailed Explanation + +#### Section 1: Header + +Each source map begins with the source map header. This is a special declarative comment which has the text "Begin source map.". If the source map is a composite source map, then text will instead read: "Begin composite source map.". + +Following the declarative comment, the metadata object contains a version key/value pair. Debuggers are expected to support at least a single major version. Minor version increases are allowed to add metadata (or extra sections), but are not allowed to remove or break existing implementations. Breaking changes must result in a major version increase. + +Keys (case sensitive): + +* version - Number - The version of the source map spec to which this file was generated. Required. +* All other keys MUST be namespaced + +A composite source map can be used when independent script files, each with their own source map, are combined into a single script that is served to the client. In the combined script, other script code may be included before, after, or in between the individual script files. For example, we could wrap the script in an anonymous function by adding an extra line at the top and at the bottom. However, the individual script files must be included whole, not split up into pieces. Furthermore, a composite source map requires that the individual script files each start on their own line. Hence, we can break the combined combined script up into a sequence of contiguous regions of lines, where each region is either an individual script file (in its entirety) or additional script with no source mapping. + +In a composite source map, the metadata object includes extra information: + +Keys (case sensitive): + +* map\_sizes - Array of numbers - The size in characters of the source maps of each of the individual source files. Required. +* map\_start\_lines - Array of numbers - The (zero-based) index of the line of the composite script file at which each individual script file starts. Required. +* map\_end\_lines - Array of numbers - The (zero-based) index of the line of the composite script file just after each individual script file ends (i.e., the range is exclusive on this end). Required. + +Each of these arrays contains one entry for each individual script included in the combined script. Hence, all three arrays must have the same length. Following the header line, a composite source map includes the source maps of each individual script. A composite source map parser can use the map\_sizes array to determine which characters of the file, after the initial line, are part of which script. The sum of all these sizes plus the length of the initial line must equal the total size of the file. Each individual source map that follows must be a valid non-composite source map, as defined by this specification. In particular, each includes its own header and all the other required sections. + +#### Section 2: File listings + +Header: /\*\* Begin file list. \*\*/ { 'count': 2 } + +The second section of the source map is a listing of all the input files that were used to create the file(s) that the source map describes. Each entry represents a single input file and must be of the form: + +\[ uriString, { optional metadata object }\] + +* uriString - String - The String URI pointing to the input file. Must be a resource that can be opened by a normal browser (such as a URL). If no such resource exists, then a pseudo-url can be used in its place and the metadata flag 'internalUri' must be set. +* metadata object - The optional metadata object for this file. + * lang - String - The language of the input file. Standard options include: 'js', 'java'. If omitted, 'js' is assumed. - Optional + * internalUri - boolean - If the URI string is not a global URL, then this flag must be set to true so debuggers know to invoke a custom handler of some sort (or none at all) + * ranges - Array -  An array of pairs of ranges at elements N and N+1, indicating the ranges of the generated code that this file covers - Optional. + * All other keys MUST be namespaced + +#### Section 3: Character Mappings + +Header: /\*\* Begin character map. \*\*/ { 'count': 1 } + +The third section of the source map is a map of a character on a given line to a mapping entry. This section is used to map from the generated code back to the original input code in an O(1) fashion. Each line of the character mappings is an array containing N entries, where N is the size of the corresponding generated line of code. For each generated line L of JavaScript, a corresponding line L + offset (where offset is the line where the character mappings begin) must exist in the source map file. + +For example, line Q in the file foo.js, might look like this: + +alert('hello world!') + +and have a corresponding character mapping line in the source map like so: + +\[0,,,,-1,1,,,,,,,,,,,,,-1\] + +Looking up the character 'e', for example, in the 'alert' would mean looking at entry #2 (0-based offset) in the array, which would indicate to us the corresponding map to use. + +There are three possible entry types: + +* E >= 0 - Use the map with ID E +* E == -1 - No mapping exists for this character (i.e. compiler added code or something similar) +* E == undefined - Use the last non-undefined entry. Should we just drop this part and always specify the mapping index? -Joseph Schorr 9/29/09 6:25 PM + +#### Section 4: Mapping Definitions + +Header: /\*\* Begin mapping definitions. \*\*/ { 'count': 4 } + +The fourth section of the source map contains an ordered list of the mapping definitions referred to in section three by the character maps. Each mapping definition is an array consisting of the following information: + +\[ file index, line number, column number,  { optional metadata object }\] + +Entries: + +* file index - Integer - The index into the file listing of which file this mapping refers to. +* line number - Integer - The line number in that file +* column number - Integer - The column position on that line +* Metadata object - Optional information for this mapping: + * originalName - String - if specified, the original name of the token, whether a variable name, member access or basic identifier. + * All other keys MUST be namespaced + +#### Section 5: Exception Mappings + +Header: /\*\* Begin exception mappings. \*\*/ { count: 2, delimeter: '\\b' } + +* delimeter - String - The delimeter to use in messages - Required + +An optional (in that it can be empty with a 'count' of 0) section, which allows generators to replace strings in throw statements with shortened delimeted commands. For example, a generator might want to replace: + +if (someError) { + + throw "I could not complete the " + someName + " operation because: " + + + someReason; + +} + +with + +if (someError) { + + throw "1\\b" + someName + "\\b" + someReason; + +} + +This would tell the debugger to look for exception mapping #1, and replace the values %1 and %2 with the string values found. + +Each exception mapping entry looks lik: + +\[file index, "I could not complete the %1 operation because: %2", { optional metadata }\] + +where the file index is the index into the file map above. + +#### Section 6 - Onward: Custom sections + +Header: /\*\* com.google.mygenerator.customsection. \*\*/{'count': 1} + +All additional sections are custom and implementaiton is left to the generators and debuggers. + +### Finding and using source maps + +Debuggers are encouraged to allow developers to load source maps manually via their UI and/or command line. In addition to manual loading of source maps, debuggers \*must\* support the ability to find source maps (if the option is turned on) by reading in the generated JavaScript files. This can be done by looking in the generated JavaScript on the first line for a comment like so: + +/\*\* @sourcemap{URL-to-the-source-map} \*\*/code begins here. + +If a debugger finds such a comment, they should follow the URL, evaluate the source map found at that location (if it is valid, of course), and display the results as if the developer had opened the source map manually. + +Generators are encouraged to add such declarations only in debug mode, or when visited from a subset of IP addresses. diff --git a/source-map-rev2.md b/source-map-rev2.md new file mode 100644 index 0000000..adb7eb1 --- /dev/null +++ b/source-map-rev2.md @@ -0,0 +1,193 @@ +# Source Map Revision 2 Proposal + +Applying lessons learned to the first revision + +John Lenz, Google + +August 10, 2010 + +This document is superseded by [Revision 3](./source-map-rev3.md). + +## Document Revisions + +Date | Author | Comment +--- | --- | --- | +August 10, 2010 | John Lenz | Initial Revision +August 12, 2010 | John Lenz | minor corrections + +## Background + +The original source map format grew out of the Closure Inspector project. It was designed for one thing: make it easy for Closure Inspector to reference the original source locations and names. This led to a couple of interesting design choices that make the original source map overly large and difficult to extend. Here we propose a new format for source mapping designed to minimize the overall size while still facilitating easy look up and adding the ability to have third party extensions. + +### Overview of the Revision 1 format + +``` + 1. /** Begin line maps. **/{ "file":"out.js", "count": 2 } + 2. [0,0,0,0,0,0,1,1,1,1,2] + 3. [2,2,2,2,2,2,3,4,4,4,4,4] + 4. /** Begin file information. **/ + 5. ["a.js", "b.js"] + 6. ["b.js", "c.js", "d.js"] + 7. /** Begin mapping definitions. **/ + 8. ["a.js", 1, 34] + 9. ["a.js", 5, 2] +10. ["b.js", 1, 3, "event"] +11. ["c.js", 1, 4] +12. ["d.js", 3, 78, "foo"] +``` + +Note: the file as a whole is not valid JSON the arrays are not part of object or an array. + +Line 1: a magic comment followed by object with a "count" field. + +Line 2: begins a block of text where each line represents a line in the generated output. Each character in the generated source has an entry id which is used to map back to the original source. + +Line 4: a magic comment + +Line 5: begins a block of text where each line represents a line in the generated output listing the original source files associated with the generated line. + +Line 7: a magic comment + +Line 8: begins a block where each line represent a mapping entry with starting line and column information and an optional original symbol name. + +## Proposed Revision 2 format + +### General Goals + +* Create a format that is parseable as a whole as standard JSON. +* Reduce the redundancy in the format + * Use indexes for file name + * remove the "file information section" + * allow for a file prefix + * allow for gzip output +* Allow the format to carry "ride along" data to faciliate additional use cases. + +### Proposal 1 - Redundancy Reduction + +``` + 1. { + 2. version: 2, + 3. file: "out.js" + 4. lineMaps: [ + 5. [1,,,,2,,,,2], + 6. [2,,3,,,,,,3] + 7. ], + 8. sourceRoot : "", + 9. sources: ["foo.js", "bar.js"], +10. names: ["src", "maps", "are", "fun"], +11. mappings: [ +12. [1, 1, 2, 4], +13. ["gack.js" 2, 1, 2, "yack"], +14. ], +15. } +``` + +Line 1: The entire file is a single JSON object + +Line 2: File revision (always the first entry in the object) + +Line 3: The name of the file that this source map is assocaiated with. + +Line 4: "lineMaps" field a JSON array, where each entry represents a line in the generated text. + +Line 5: A line entry, where each entry represents a character in the line, an empty field represents repeated value. The first entry and last entries are never a "repeating value". + +Line 8: An optional source root, useful for relocating source files on a server or removing repeated values in the "sources" entry. + +Line 9: A list of sources used by the "mappings" entry. ~~This list may be incomplete.~~ + +Line 10: A list of symbol names used by the "mapping" entry. This list may be incomplete. + +Line 11: The mappings field. + +Line 12: Each entry represent a block of text in the original source, and consists four fields: + +* The source file name +* The line in the source file the text begins +* The column in the line that the text begins +* An optional name (from the original source) that this entry represents. This can either be an string or index into the "names" field. +* ~~An optional object containing **namespaced** keys for compiler-specific metadata.~~ + +~~The mappings entry for the source file and symbol name are optionally indexes into the sources and names entries.~~ + +#### Encoding + +The character set encoding is UTF-8. + +#### Compression + +The file is allowed to be GZIP compressed. It is not expected that in-browser consumers of the the source map will support GZIP compression directly but that they will consume an uncompressed map that may be GZIPd for transport. + +#### Extensions + +Additional fields may be added to the top level source map provided the fields begin with the "x\_" naming convention. It is expected that the extensions would be classified by the project providing the extension, such as "x\_inspector\_extradata". Field names outside the "x\_" namespace are reserved for future revisions. + +#### Long Line Handling + +For generated text that consist of a single very long line. It would be possible to split the line into known fix size pieces by replacing a lineMaps entry with an JSON object: + +``` + 1. linesMaps: [{ + 2. segment: 512, + 3. [1,...], // first 512 characters of the line + 4. [2,...], // second 512 characters of the line + 5. // etc + 6. }], +``` + +#### Additional Notes + +With this format the source map file size is approximately 1/4 of the size of the Revision 1 format in typical use. + +### Proposal 2 - Alternate encoding + +This proposal start with basic concepts as Proposal 1 but changes the lineMappings entry. The basic idea is to use a string rather than an array and to use Base64 encoding for the mapping ids and run length. + +To find an value for a character, the line is decoded from the beginning of the string until a segment is found that matches character of interest (it is expected that in the normal use case, the line will be decoded once, and stored for later reference). + +#### Segment description + +Each segment entry in the string would have one Base64 digit encoding the length of the encoded map id and the run-length of the segment. Since the base-64 character encodes 6-bits, it is divided up: + +2 bits for map id encoding size (1-4 base64 digits) + +4 bits for run-length (1-16 repetitions) + +The next 1-4 characters represent the map id. As mapping ids are expected to be sequential and generally clustered, the mapping ids in a given lineMappings entry are relative to the previous mapping (as a signed number) .  The first mapping id of the lineMapping is offset relative to zero. + +This would change the current source maps from something like this + +``` +[1,1,1,2,3] +``` + +into: + +``` +"CAAAAA" +``` + +Given a sample like the following, which has already be optimized for repetitions as in Proposal 1, it is easy to see the space saving that would result from this scheme, as most of the ids are large and are just a few indexes away from each other: + +``` +[79901,79883,79902,79883,79880,79904,,79903,79905,,,,79903,79906,,,,,,,,79907,,79908,79911,79910,,,79909,79912,79909,79913,79909,79914,79909,79915,79909,79917,,79916,79918,79916,79919,,79916,79920,,,,,,,79916,79921,79916,79908] +``` + +##### Large ids or many repetitions + +As described, the encoding imposes a limit on the size of the source as mapping ids larger than 2^24 (~8M mappings) that can be mapped source map file and limits run lengths to 16. This limit is lifted by using characters outside the base64 encoding as special markers (ascii alpha-numerics are used, as well as ‘+’ and ‘/’). A "!" is used to indicate "big" values and both the id size and the repetition get full base-64 characters (6 bits), so it would look like "!EA012aZ". For ids, the use of relative ids for the rest of the line, means that most likely, this would only be used rarely. In practice this is only used for long repetitions. Repetition of the "!" is used, so that "!!!!" means 4 digits values for id and repetition value. For repetitions this is a very acceptable trade off. + +#### Example lineMapping entries + +``` +'ehIREhAhAhAfAiAeAjIhAhAfMiMhEhAhAeEjAiAfAiAeAbAoAYApAXEqAhAVAtAfAjAfAiAeAeAlAbAR', +'ehIrIhAhAhAfAiAeAjAdAkIhAhAfMiMhAhIeEjAdIkAhEfAiAi4fEdAn4fAfAjAdAbAqAfAiAeAkAfAiAeAdAQ', +'ehJHIhAhAhAfAiAeAjIhAi4fAfUjEj4fAfAjAdQcAoMhMhAhIeEjAdIkAhEfAiAeUjEhYhEhAVAX', +'ehJhIhAhAhAfAiAeAjAdAkMhMhAhAfEiAiAfAiAeAdEmAhAYApAXAqAWErAhAUAtMhEhAjQfAfAkAfAiAeAdEnAfAjEfAiAeAjAdAlAfAiAeAjAdARUzEhBfe', +'ehKKIhAhAhAfAiAeAjMhMhEhEhAeEjAiAfAiAeAcEnAhAXAqAWArAVEsAhATAwQfAfAkAfAjAfAiAeAeAlAbAdYpEhAH', +'ehKpIhAhAhAfAiAeAjAdAkAcAlAiAfEjAfAiAeAjAdElAfEjAfAiAeAkAfAiAeAdQmAhAfAiAeAjAdAkAcElAhAaApQfAfAkAfAiAeAdAK', +``` + +#### Affect on source map size + +The size of the source map is reduced another 20-30% over the Proposal 1. diff --git a/source-map-rev3.md b/source-map-rev3.md new file mode 100644 index 0000000..bbc2e23 --- /dev/null +++ b/source-map-rev3.md @@ -0,0 +1,285 @@ +# Source Map Revision 3 Proposal + +Better bidirectional mapping. + +John Lenz, Google + +Nick Fitzgerald, Mozilla + +February 11, 2011 + +## Document Revisions + +Date | Author | Comment +--- | --- | --- +April 12, 2011 | John Lenz | Initial Revision +April 15, 2011 | John Lenz | Updates to reflect prototype +July 20, 2011 | John Lenz | Removed “lineCount” field, remove “Combined Map” section +August 18, 2011 | John Lenz | Draft +May 2, 2012 | John Lenz | HTTP header and CC-BY-SA license +July 30, 2012 | John Lenz | Modified recommended HTTP header name. +August 20, 2012 | John Lenz | Add CSS linkage recommendation +October 24, 2012 | John Lenz | Add clarifying section on source locations. +February 19, 2013 | John Lenz | Add “sourcesContent” line to support self contained source maps.

Added note regarding using data uri to load source maps. +May 16, 2013 | John Lenz | Updated linking convention to use # instead of @. @ conflicts with internet explorer’s conditional code +November 18, 2013 | John Lenz | Noted that “file” is an optional field.

Minor typographical corrections + +## License + +This work is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License](http://creativecommons.org/licenses/by-sa/3.0/). + + +## Discussion + +To discuss or propose changes to this specification, please use the dev-js-sourcemap mailing list: [https://lists.mozilla.org/listinfo/dev-js-sourcemap](https://lists.mozilla.org/listinfo/dev-js-sourcemap) + + +## Background + +The original source map format (v1) was created by Joseph Schorr for use by Closure Inspector to enable source level debugging of optimized JavaScript code (although the format itself is language agnostic). However, as the size of the projects using the source maps expanded the verbosity of the format started to be become a problem. The v2 was created trading some simplicity and flexibility to reduce to overall size of the source map. Even with the changes made with the v2 version of the format, the source map file size was limiting its usefulness. The v3 format is based on suggestions made by podivilov@. + +Related documents: + +[Revision 2 proposal](https://docs.google.com/document/d/1xi12LrcqjqIHTtZzrzZKmQ3lbTv9mKrN076UB-j3UZQ/edit?hl=en_US) + + +## Terminology + + +Term | Definition +--- | --- +Generated Code | The code which is generated by the compiler. +Original Source | The source code which has not been passed through the compiler. +Base 64 VLQ | The VLQ is a Base64 value, where the most significant bit (the 6th bit) is used as the continuation bit, and the “digits” are encoded into the string least significant first, and where the least significant bit of the first digit is used as the sign bit.

Note: The values that can be represent by the VLQ Base64 encoded are limited to 32 bit quantities until some use case for larger values is presented. +Source Mapping URL | The URL referencing the location of a source map from the generated code. + +## Revision 3 Format + + +### General Goals + + + +* Reduce the overall size to improve parse time, memory consumption, and download time. +* Support source level debugging allowing bidirectional mapping +* Support server side stack trace deobfuscation + + +### Proposed Format + + + +1. `{` +2. `"version" : 3,` +3. `"file": "out.js",` +4. `"sourceRoot": "",` +5. `"sources": ["foo.js", "bar.js"],` +6. `"sourcesContent": [null, null],` +7. `"names": ["src", "maps", "are", "fun"],` +8. `"mappings": "A,AAAB;;ABCDE;"` +9. `}` + +Line 1: The entire file is a single JSON object + +Line 2: File version (always the first entry in the object) and must be a positive integer. + +Line 3: An optional name of the generated code that this source map is associated with. + +Line 4: An optional source root, useful for relocating source files on a server or removing repeated values in the “sources” entry. This value is prepended to the individual entries in the “source” field. + +Line 5: A list of original sources used by the “mappings” entry. + +Line 6: An optional list of source content, useful when the “source” can’t be hosted. The contents are listed in the same order as the sources in line 5. “null” may be used if some original sources should be retrieved by name. + +Line 7: A list of symbol names used by the “mappings” entry. + +Line 8: A string with the encoded mapping data. + +The “mappings” data is broken down as follows: + + + +* each group representing a line in the generated file is separated by a ”;” +* each segment is separated by a “,” +* each segment is made up of 1,4 or 5 variable length fields. + +The fields in each segment are: + + + +1. The zero-based starting column of the line in the generated code that the segment represents. If this is the first field of the first segment, or the first segment following a new generated line (“;”), then this field holds the whole base 64 VLQ. Otherwise, this field contains a base 64 VLQ that is relative to the previous occurrence of this field. _Note that this is different than the fields below because the previous value is reset after every generated line._ +2. If present, an zero-based index into the “sources” list. This field is a base 64 VLQ relative to the previous occurrence of this field, unless this is the first occurrence of this field, in which case the whole value is represented. +3. If present, the zero-based starting line in the original source represented. This field is a base 64 VLQ relative to the previous occurrence of this field, unless this is the first occurrence of this field, in which case the whole value is represented. Always present if there is a source field. +4. If present, the zero-based starting column of the line in the source represented. This field is a base 64 VLQ relative to the previous occurrence of this field, unless this is the first occurrence of this field, in which case the whole value is represented. Always present if there is a source field. +5. If present, the zero-based index into the “names” list associated with this segment. This field is a base 64 VLQ relative to the previous occurrence of this field, unless this is the first occurrence of this field, in which case the whole value is represented. + +Note: This encoding reduces the source map size 50% relative to the V2 format in tests performed using Google Calendar. + + +#### Resolving Sources + +If the sources are not absolute URLs after prepending of the “sourceRoot”, the sources are resolved relative to the SourceMap (like resolving script src in a html document). + + +#### Encoding + +For simplicity, the character set encoding is always UTF-8. + + +#### Compression + +The file is allowed to be GZIP compressed. It is not expected that in-browser consumers of the the source map will support GZIP compression directly but that they will consume an uncompressed map that may be GZIP’d for transport. + + +#### Extensions + +Additional fields may be added to the top level source map provided the fields begin with the “x_” naming convention. It is expected that the extensions would be classified by the organization providing the extension, such as “x_google_linecount”. Field names outside the “x_” namespace are reserved for future revisions. It is **recommended** that fields be namespaced by domain, i.e. x_com_google_gwt_linecount. + + +##### Known Extensions + +“x_google_linecount” - the number of lines represented by this source map. + + +#### Notes + +Using file offsets were considered but rejected in favor of using line/column data to avoid becoming misaligned with the original due to platform specific line endings. + + +#### Index map: supporting post processing + +To support concatenating generated code and other common post processing, an alternate representation of a map is supported: + + + +1. `{` +2. `"version" : 3,` +3. `"file": "app.js",` +4. `"sections": [` +5. ` { "offset": {"line":0, "column":0}, "url": "url_for_part1.map" }` +6. ` { "offset": {"line":100, "column":10}, "map": ` +7. ` {` +8. ` "version" : 3,` +9. ` "file": "section.js",` +10. ` "sources": ["foo.js", "bar.js"],` +11. ` "names": ["src", "maps", "are", "fun"],` +12. ` "mappings": "AAAA,E;;ABCDE;"` +13. ` }` +14. ` }` +15. `],` +16. `}` + +The index map follow the form of the standard map + +Line 1: The entire file is an JSON object. + +Line 2: The version field. See the description of the standard map. + +Line 3: The name field. See the description of the standard map. + +Line 4: The sections field. + +The “sections” field is an array of JSON objects that itself has two fields “offset” and a source map reference. “offset” is an object with two fields, “line” and “column”, that represent the offset into generated code that the referenced source map represents. + +The other field must be either “url” or “map”. A “url” entry must be a URL where a source map can be found for this section and the url is resolved in the same way as the “sources” fields in the standard map. A “map” entry must be an embedded complete source map object. An embedded map does not inherit any values from the containing index map. + +The sections must be sorted by starting position and the represented sections may not overlap. + + +### Conventions + + +#### Source Map Naming + +Optionally, a source map will have the same name as the generated file but with a “.map” extension. For example, for “page.js” a source map named “page.js.map” would be generated. + + +#### Linking generated code to source maps + +While the source map format is intended to be language and platform agnostic, it is useful to have a some conventions for the expected use-case of web server hosted javascript. + +There are two suggested ways to link source maps to the output. The first requires server support to add a HTTP header and the second requires an annotation in the source. + +The HTTP header should supply the source map URL reference as: + + + + +``` + SourceMap: +``` + + +Note: previous revisions of this document recommended a header name of “X-SourceMap”. This is now deprecated; “SourceMap” is now expected. + +The generated code may include a line at the end of the source, with the following form: + + +``` + //# sourceMappingURL= +``` + + +Note: The prefix for this annotation was initially “//@” however this conflicts with Internet Explorer’s Conditional Compilation and was changed to “//#”. It is reasonable for tools to also accept “//@” but “//#” is preferred. + +This recommendation works well for JavaScript, it is expected that other source files will have other conventions: + + + + + + + +
CSS + /*# sourceMappingURL=<url> */ +
+ + +Note: <url> is a URL as defined in RFC3986; in particular, characters outside the set permitted to appear in URIs must be percent-encoded. + +Note: <url> maybe a data URI. Using a data URI along with “sourcesContent” allow for a completely self-contained source-map. + +Regardless of the method used to retrieve the source mapping URL the same process is used to resolve it, which is as follows: + + When the source mapping URL is not absolute, then it is relative to the generated code’s “source origin”. The source origin is determined by one of the following cases: + + + +* If the generated source is not associated with a script element that has a “src” attribute and there exists a `//# sourceURL` comment in the generated code, that comment should be used to determine the source origin. Note: Previously, this was “//@ sourceURL”, as with “//@ sourceMappingURL”, it is reasonable to accept both but //# is preferred. +* If the generated code is associated with a script element and the script element has a “src” attribute, the “src” attribute of the script element will be the source origin. +* If the generated code is associated with a script element and the script element does not have a “src” attribute, then the source origin will be the page’s origin. +* If the generated code is being evaluated as a string with the `eval()` function or via `new Function()`, then the source origin will be the page’s origin. + + +#### Linking eval’d code to named generate code + +There is an existing convention that should be supported for the use of source maps with eval’d code, it has the following form: + + +``` + //# sourceURL=foo.js +``` + + +It is described here: + +[https://web.archive.org/web/20120814122523/http://blog.getfirebug.com/2009/08/11/give-your-eval-a-name-with-sourceurl/](https://web.archive.org/web/20120814122523/http://blog.getfirebug.com/2009/08/11/give-your-eval-a-name-with-sourceurl/) + + +### Language Neutral Stack Mapping Notes + +Stack tracing mapping without knowledge of the source language is not covered by this document. + + +### Multi-level Mapping Notes + +It is getting more common to have tools generate source from some [DSL](http://en.wikipedia.org/wiki/Domain-specific_language) (templates) or to compile CoffeeScript -> JavaScript -> minified JavaScript, resulting in multiple translations before the final source map is created. This problem can be handled in one of two ways. The easy but lossy way is to ignore the intermediate steps in the process for the purposes of debugging, the source location information from the translation is either ignored (the intermediate translation is considered the “Original Source”) or the source location information is carried through (the intermediate translation hidden). The more complete way is to support multiple levels of mapping: if the Original Source also has a source map reference, the user is given the choice of using the that as well. + +However, It is unclear what a “source map reference” looks like in anything other than JavaScript. More specifically, what a source map reference looks like in a language that doesn’t support JavaScript style single line comments. An HTTP header would address this, but is not yet agreed upon. + + +### JSON over HTTP Transport + +[XSSI](http://googleonlinesecurity.blogspot.com/2011/05/website-security-for-webmasters.html) attacks could potentially make source maps available to attackers by doing a direct script src to a source map after overriding the Array constructor. This can be effectively prevented by preprending a JavaScript syntax error to the start of the response. + +Thus when delivering source maps over HTTP, servers may prepend a line starting with the string “)]}'” to the sourcemap. If the response starts with this string clients must ignore the first line. diff --git a/source-map.bs b/source-map.bs new file mode 100644 index 0000000..79017c8 --- /dev/null +++ b/source-map.bs @@ -0,0 +1,462 @@ +

+Title: Source Map
+H1: Source Map
+Shortname: source-map
+Level: 1
+Status: STAGE0
+URL: https://source-map.github.io/source-map-spec/
+Editor: Armin Ronacher, Sentry
+Former Editor: Victor Porof, Google
+Former Editor: John Lenz, Google
+Former Editor: Nick Fitzgerald, Mozilla
+Previous Version: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1#
+Repository: source-map/source-map-spec
+Abstract: A specification for mapping transpiled source code (primarily JavaScript) back to the original sources.  This specification is a living document and describes a hardened version of the Source Map v3 specification.
+Markup Shorthands: markdown yes
+Group: tc39
+
+ + + +
+{
+  "VLQ": {
+    "href": "https://en.wikipedia.org/wiki/Variable-length_quantity",
+    "title": "Variable-length quantity",
+    "publisher": "Wikipedia",
+    "status": "reference article"
+  },
+  "base64": {
+    "href": "https://www.ietf.org/rfc/rfc4648.txt",
+    "id": "rfc4648",
+    "publisher": "IETF",
+    "status": "Standards Track",
+    "title": "The Base16, Base32, and Base64 Data Encodings"
+  },
+  "URL": {
+    "href": "https://url.spec.whatwg.org/",
+    "publisher": "WhatWG",
+    "status": "Living Standard",
+    "title": "URL Standard"
+  },
+  "EvalSourceURL": {
+    "href": "https://web.archive.org/web/20120814122523/http://blog.getfirebug.com/2009/08/11/give-your-eval-a-name-with-sourceurl/",
+    "publisher": "Firebug",
+    "status": "archive",
+    "title": "Give your eval a name with //@ sourceURL"
+  },
+  "V2Format": {
+    "href": "https://docs.google.com/document/d/1xi12LrcqjqIHTtZzrzZKmQ3lbTv9mKrN076UB-j3UZQ/edit?hl=en_US",
+    "publisher": "Google",
+    "title": "Source Map Revision 2 Proposal"
+  },
+  "WasmCustomSection": {
+    "href": "https://www.w3.org/TR/wasm-core-2/binary/modules.html#custom-section",
+    "publisher": "W3C",
+    "status": "Living Standard",
+    "title": "WebAssembly custom section"
+  },
+  "WasmNamesBinaryFormat": {
+    "href": "https://www.w3.org/TR/wasm-core-2/binary/values.html#names",
+    "publisher": "W3C",
+    "status": "Living Standard",
+    "title": "WebAssembly Names binary format"
+  }
+}
+
+ +## License + +This work is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License](http://creativecommons.org/licenses/by-sa/3.0/). + +## Introduction + +This document is a draft version of a hardened version of the Source Map v3 +specification. In its current form, it's not a defined standard and is subject to +modifications. If you want to get involved you will find more information under +the following GitHub repositories: + +* [Spec Repository](https://github.com/source-map/source-map-spec/): holds the different + specifications (v1, v2, v3 and the hardened v3 draft you are looking at) +* [RFC Repository](https://github.com/source-map/source-map-rfc/): meta + repository for change suggestions to the specification. + +Background {#background} +======================== + +The original source map format (v1) was created by Joseph Schorr for use by +Closure Inspector to enable source-level debugging of optimized JavaScript code +(although the format itself is language agnostic). However, as the size of the +projects using the source maps expanded the verbosity of the format started to +become a problem. The v2 ([[V2Format]]) was created by trading some simplicity +and flexibility to reduce the overall size of the source map. Even with the +changes made with the v2 version of the format, the source map file size was +limiting its usefulness. The v3 format is based on suggestions made by +Pavel Podivilov (Google). + +This document codifies the prior art that is Source Map v3 but is more specific +about the precise meanings of the specification. + +Terminology {#terminology} +========================== + +Generated Code is the code which is generated +by the compiler or transpiler. + +Original Source is the source code which has not +been passed through the compiler. + +Base64 VLQ: [[VLQ]] is a [[base64]] value, where the most significant +bit (the 6th bit) is used as the continuation bit, and the "digits" are encoded +into the string least significant first, and where the least significant bit of +the first digit is used as the sign bit. + +Note: The values that can be represented by the VLQ Base64 encoded are limited to +32-bit quantities until some use case for larger values is presented. + +Source Mapping URL refers to the URL referencing +the location of a source map from the [=Generated code=]. + +Column is the 0 (zero) indexed offsets within a line of the +generated code measured. The definition for columns in source maps can depend on +the content type. For JavaScript and CSS based source maps are defined to be in +UTF-16 code units analogous to JavaScript string indexes. That means that +"A" (`LATIN CAPITAL LETTER A`) measures 1 code unit, and "🔥" (`FIRE`) measures +2 code units. For WebAssembly, columns are defined as byte offsets from the beginning +of the binary content (and there is only one group representing a line). Source maps +for other content types might diverge from this. + + +General Goals {#general-goals} +============================== + +The goals for the v3 format of Source Maps + +* Reduce the overall size to improve parse time, memory consumption, and download time. +* Support source-level debugging allowing bidirectional mapping +* Support server-side stack trace deobfuscation + +Source Map Format {#source-map-format} +====================================== + +The source map is a JSON document containing a top-level JSON object with the +following structure: + +```json +{ + "version" : 3, + "file": "out.js", + "sourceRoot": "", + "sources": ["foo.js", "bar.js"], + "sourcesContent": [null, null], + "names": ["src", "maps", "are", "fun"], + "mappings": "A,AAAB;;ABCDE" + "ignoreList": [0] +} +``` + +Note: The previous specification suggested an order to the keys in this file, but +for practical reasons, the order cannot be defined in many JSON generators and +has never been enforced. + +version is the version field which must always be the number +`3` as an integer. The source map may be rejected in case of a value different from `3`. + +file an optional name of the generated code +that this source map is associated with. It's not specified if this can +be a URL, relative path name, or just a base name. As such it has a mostly informal +character. + +sourceRoot an optional source root, +useful for relocating source files on a server or removing repeated values in +the [=sources=] entry. This value is prepended to the individual entries in the +"source" field. + +sources is a list of original sources +used by the [=mappings=] entry. Each entry is either a string that is a +(potentially relative) URL or `null` if the source name is not known. + +sourcesContent an optional list +of source content (that is the [=Original Source=]), useful when the "source" +can't be hosted. The contents are listed in the same order as the [=sources=]. +`null` may be used if some original sources should be retrieved by name. + +names a list of symbol names used by the [=mappings=] entry. + +mappings a string with the encoded mapping data (see [[#mappings-structure]]). + +ignoreList an optional list of indices of files that +should be considered third party code, such as framework code or bundler-generated code. This +allows developer tools to avoid code that developers likely don't want to see +or step through, without requiring developers to configure this beforehand. +It refers to the [=sources=] array and lists the indices of all the known third-party sources +in the source map. Some browsers may also use the deprecated x_google_ignoreList +field if ignoreList is not present. + +Mappings Structure {#mappings-structure} +---------------------------------------- + +The [=mappings=] data is broken down as follows: + +- each group representing a line in the generated file is separated by a semicolon (`;`) +- each segment is separated by a comma (`,`) +- each segment is made up of 1, 4, or 5 variable length fields. + +The fields in each segment are: + +1. The zero-based starting [=column=] of the line in the generated code that the segment represents. + If this is the first field of the first segment, or the first segment following a new generated + line (`;`), then this field holds the whole [=Base64 VLQ=]. Otherwise, this field contains + a [=Base64 VLQ=] that is relative to the previous occurrence of this field. Note that this + is different than the fields below because the previous value is reset after every generated line. + +2. If present, a zero-based index into the [=sources=] list. This field is a [=Base64 VLQ=] + relative to the previous occurrence of this field, unless this is the first occurrence of this + field, in which case the whole value is represented. + +3. If present, the zero-based starting line in the original source is represented. This field is a + [=Base64 VLQ=] relative to the previous occurrence of this field, unless this is the first + occurrence of this field, in which case the whole value is represented. Always present if there + is a source field. + +4. If present, the zero-based starting [=column=] of the line in the source represented. This + field is a [=Base64 VLQ=] relative to the previous occurrence of this field unless this + is the first occurrence of this field, in which case the whole value is represented. Always + present if there is a source field. + +5. If present, the zero-based index into the [=names=] list associated with this segment. This + field is a base 64 VLQ relative to the previous occurrence of this field unless this + is the first occurrence of this field, in which case the whole value is represented. + +Note: This encoding reduces the source map size by 50% relative to the V2 format in tests performed +using Google Calendar. + +Resolving Sources {#resolving-sources} +-------------------------------------- + +If the sources are not absolute URLs after prepending the [=sourceRoot=], the sources are +resolved relative to the SourceMap (like resolving the script `src` attribute in an HTML document). + +Extensions {#extensions} +------------------------ + +Source map consumers must ignore any additional unrecognized properties, rather than causing the +source map to be rejected, so that additional features can be added to this format without +breaking existing users. + +Notes on File Offsets +--------------------- + +Using file offsets was considered but rejected in favor of using line/column data to avoid becoming +misaligned with the original due to platform-specific line endings. + +Index Map +========= + +To support concatenating generated code and other common post-processing, +an alternate representation of a map is supported: + +```json +{ + "version" : 3, + "file": "app.js", + "sections": [ + { + "offset": {"line": 0, "column": 0}, + "map": { + "version" : 3, + "file": "section.js", + "sources": ["foo.js", "bar.js"], + "names": ["src", "maps", "are", "fun"], + "mappings": "AAAA,E;;ABCDE" + } + }, + { + "offset": {"line": 100, "column": 10}, + "map": { + "version" : 3, + "file": "another_section.js", + "sources": ["more.js"], + "names": ["more", "is", "better"], + "mappings": "AAAA,E;AACA,C;ABCDE" + } + } + ] +} +``` + +The index map follows the form of the standard map. Like the regular source map, +the file format is JSON with a top-level object. It shares the [=version=] and +[=file=] field from the regular source map, but gains a new [=sections=] field. + +sections is an array of JSON objects that itself has two +fields [=offset=] and [=map=]. + +## Section + +offset is an object with two fields, `line` and `column`, +that represent the offset into generated code that the referenced source map +represents. + +map is an embedded complete source map object. +An embedded map does not inherit any values from the containing index map. + +The sections must be sorted by starting position and the represented sections +may not overlap. + +Conventions {#conventions} +========================== + +The following conventions should be followed when working with source maps or +when generating them. + +Source Map Naming {#source-map-naming} +-------------------------------------- + +Optionally, a source map will have the same name as the generated file but with a `.map` +extension. For example, for `page.js` a source map named `page.js.map` would be generated. + +Linking generated code to source maps {#linking-generated-code} +--------------------------------------------------------------- + +While the source map format is intended to be language and platform agnostic, it is useful +to have some conventions for the expected use-case of web server-hosted JavaScript. + +There are two suggested ways to link source maps to the output. The first requires server +support in order to add an HTTP header and the second requires an annotation in the source. + +The HTTP header should supply the source map URL reference as: + +``` +sourcemap: +``` + +Note: Previous revisions of this document recommended a header name of `x-sourcemap`. This +is now deprecated; `sourcemap` is now expected. + +The generated code should include a line at the end of the source, with the following form: + +``` +//# sourceMappingURL= +``` + +Note: The prefix for this annotation was initially `//@` however this conflicts with Internet +Explorer's Conditional Compilation and was changed to `//#`. Source map generators must only emit `//#` +while source map consumers must accept both `//@` and `//#`. + +Note: `//@` is needed for compatibility with some existing legacy source maps. + + +This recommendation works well for JavaScript, but it is expected that other source files will +have different conventions. For instance, for CSS `/*# sourceMappingURL= */` is proposed. +On the WebAssembly side, such a URL is encoded using [[WasmNamesBinaryFormat]], and it's placed as the content of the custom section ([[WasmCustomSection]]) named `sourceMappingURL`. + +`` is a URL as defined in [[URL]]; in particular, +characters outside the set permitted to appear in URIs must be percent-encoded +and it may be a data URI. Using a data URI along with [=sourcesContent=] allows +for a completely self-contained source map. + +The HTTP `SourceMap` header has precedence over a source annotation, and if both are present, +the header URL should be used to resolve the source map file. + +Regardless of the method used to retrieve the [=Source Mapping URL=] the same +process is used to resolve it, which is as follows: + +When the [=Source Mapping URL=] is not absolute, then it is relative to the generated code's +source origin. The [=source origin=] is determined by one of the following cases: + +- If the generated source is not associated with a script element that has a `src` + attribute and there exists a `//# sourceURL` comment in the generated code, that + comment should be used to determine the [=source origin=]. Note: Previously, this was + `//@ sourceURL`, as with `//@ sourceMappingURL`, it is reasonable to accept both + but `//#` is preferred. + +- If the generated code is associated with a script element and the script element has + a `src` attribute, the `src` attribute of the script element will be the [=source origin=]. + +- If the generated code is associated with a script element and the script element does + not have a `src` attribute, then the [=source origin=] will be the page's origin. + +- If the generated code is being evaluated as a string with the `eval()` function or + via `new Function()`, then the [=source origin=] will be the page's origin. + +Linking eval'd code to named generated code +------------------------------------------- + +There is an existing convention that should be supported for the use of source maps with +eval'd code, it has the following form: + +``` +//# sourceURL=foo.js +``` + +It is described in [[EvalSourceURL]]. + +Language Neutral Stack Mapping Notes +==================================== + +Stack tracing mapping without knowledge of the source language is not covered by this document. + +Multi-level Mapping Notes +========================= + +It is getting more common to have tools generate sources from some DSL (templates) or compile +TypeScript -> JavaScript -> minified JavaScript, resulting in multiple translations before the +final source map is created. This problem can be handled in one of two ways. The easy but +lossy way is to ignore the intermediate steps in the process for the purposes of debugging, +the source location information from the translation is either ignored (the intermediate +translation is considered the “Original Source”) or the source location information is carried +through (the intermediate translation hidden). The more complete way is to support multiple +levels of mapping: if the Original Source also has a source map reference, the user is given +the choice of using that as well. + +However, It is unclear what a "source map reference" looks like in anything other than JavaScript. +More specifically, what a source map reference looks like in a language that doesn't support +JavaScript-style single-line comments. + +Fetching Source Maps {#fetching-source-maps} +============================================ + +To fetch a source map given a [=URL=] |url|, run the following steps: + +1. Let |promise| be [=a new promise=]. +1. Let |request| be a new [=request=] whose [=request/URL=] is |url|. +1. [=Fetch=] |request| with [=processResponseConsumeBody=] set to the following steps given [=response=] response and null, failure, or a [=byte sequence=] |bodyBytes|: + 1. If |bodyBytes| is null or failure, [=reject=] |promise| with a {{TypeError}} and abort these steps. + 1. If |url|'s [=url/scheme=] is an [=HTTP(S) scheme=] and |bodyBytes| [=byte sequence/starts with=] \`)]}'\`, then: + 1. [=While=] |bodyBytes|'s [=byte sequence/length=] is not 0 and |bodyBytes|'s 0th byte is not an [=HTTP newline byte=]: + 1. remove the 0th byte from |bodyBytes|. + +
+ Note: For historic reasons, when delivering source maps over HTTP(S), servers may prepend a line + starting with the string `)]}'` to the source map. + + ``` + )]}'garbage here + {"version": 3, ...} + ``` + + is interpreted as + + ``` + {"version": 3, ...} + ``` +
+ 1. Let |sourceMap| be the result of [=parsing JSON bytes to a JavaScript value=] given |bodyBytes|. + 1. If the previous step threw an error, [=reject=] |promise| with that error. + 1. Otherwise, [=resolve=] |promise| with |sourceMap|. +1. Return |promise|.