{"id":13701027,"url":"https://github.com/tc39/proposal-built-in-modules","last_synced_at":"2025-04-12T19:48:50.915Z","repository":{"id":47508531,"uuid":"140954496","full_name":"tc39/proposal-built-in-modules","owner":"tc39","description":null,"archived":false,"fork":false,"pushed_at":"2023-06-02T05:05:32.000Z","size":5102,"stargazers_count":896,"open_issues_count":40,"forks_count":24,"subscribers_count":288,"default_branch":"master","last_synced_at":"2025-04-12T19:48:35.891Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tc39.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}},"created_at":"2018-07-14T14:56:38.000Z","updated_at":"2025-01-08T20:39:33.000Z","dependencies_parsed_at":"2024-01-06T01:05:51.166Z","dependency_job_id":"3503d210-95d3-4593-9e1b-9ccc1fe8d3a0","html_url":"https://github.com/tc39/proposal-built-in-modules","commit_stats":null,"previous_names":["tc39/proposal-javascript-standard-library"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tc39%2Fproposal-built-in-modules","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tc39%2Fproposal-built-in-modules/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tc39%2Fproposal-built-in-modules/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tc39%2Fproposal-built-in-modules/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tc39","download_url":"https://codeload.github.com/tc39/proposal-built-in-modules/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248625501,"owners_count":21135513,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":"2024-08-02T20:01:14.576Z","updated_at":"2025-04-12T19:48:50.881Z","avatar_url":"https://github.com/tc39.png","language":"HTML","funding_links":[],"categories":["HTML"],"sub_categories":[],"readme":"# Built In Modules Proposal (aka JavaScript Standard Library)\n\nProposal for adding a mechanism for enabling a more extensive standard library in JavaScript \nvia a collection of built in modules. With this infrastructure in place it will be possible\nto start iterating on standard library features as additional modules.\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003cstrong\u003eTable of Contents\u003c/strong\u003e\u003c/summary\u003e\n\n  * [Scope](#scope)\n  * [Motivation](#motivation)\n  * [Proposed Solution](#proposed-solution)\n  * [Import Semantics](#import-semantics)\n  * [Module Resolution](#module-resolution)\n  * [Related Efforts](#related-efforts)\n  * [Frequently Asked Questions](#frequently-asked-questions)\n  * [Appendices](#appendices)\n  * [Specification](#specification)\n  * [Implementations](#implementations)\n\n\u003c/details\u003e\n\n## Scope\n\nThe goal of this proposal is to define a mechanism for enabling a more extensive standard library in\nJavaScript than what is available now.  Currently it is the case if new properties are added to the\nlanguage, they are added someplace in the global object.  \n\nThis proposal would not change the behavior of any existing code or add any new syntax, except possibly\nsyntax needed for importing the standard library code.  There likely will be new properties and methods\nadded to enable this feature.\n\nThe contents of the standard library is tangential to this proposal, and would be built and expanded upon in\nlater efforts. Such a library would only cover features which would be useful in JavaScript in general, not\nthings which are tied to the web platform.  Host environments built on JavaScript could provide their own\nlibrary components.  (A good heuristic: if something would make sense on a web browser\nbut not in node or on [embedded devices](https://www.moddable.com/) or [robots](http://johnny-five.io/), it\nprobably isn't in scope.) See [#16](https://github.com/tc39/proposal-built-in-modules/issues/16)\nfor discussion of the extent and contents of the library.\n\n## Motivation\n\nMost programming languages have core language features (syntax, operators, primitives etc.) along with a \nstandard library of commonly used functionality. Developers are able to use this library in their programs\nimmediately because the library is bundled with the runtime.\n\nThe JavaScript language does not have a standard library.\nAs a result new functionality is added to the global object, or developers find and adopt libraries that\nthey bundle with the rest of their application.\nBecause these libraries need to be included in every program instead of being provided by the runtime,\nthe code size of applications grow, with users paying the cost of downloading and parsing the common library components.\nThis can increase downloading times and makes it nearly impossible for JavaScript engines to cache the common code.\n\nJavaScript programs run on a variety of clients with different runtime implementations and versions.\nIt is quite likely that the bundled library code needs to account for different host environments,\nthus increasing code size.\nLibrary code bundled with the JavaScript engine could be optimizied for the target host environment.\n\n## Proposed Solution\n\nTo enable developers to access common functionality provided by the JavaScript engine we propose creating\nmodules built into the host.\nThis will allow library code bundled with the program to shift towards being available on the host JavaScript\nimplementations.\n\n\u003e Disclaimer: This proposal covers adding a mechanism for enabling a standard library in JavaScript\n\u003e implementations, it does not describe its contents. This is considered a tangential effort that would\n\u003e be built and expanded upon in the future when a mechanism for accessing it is in place.\n\nHaving a standard library readily available at runtime means programs won't have to include the functionality\navailable in the standard library, reducing the download and startup cost of the program.\nThe functionality will also be standardized across implementations giving developer consistency in quality, behavior and\nspeed.\nFor some JavaScript engines, built in modules will allow them to reduce application memory footprint\n\nAlthough JavaScript engines already has the notion of a common library through the global object,\nthe standard library components can be accessed using the current asynchronous `import()` API.\nModule scripts can also access built in library components using the `import` syntax.\nTraditional script code will be able to access these same standard library components through\na new synchronous API, `importNow()`.\nMost of these mechanism should already be familiar to developers, allowing them to opt-in to\nthis built in library functionality with little effort.\n\nModules for the standard library should be able to be written in plain JavaScript for the most part but for\nhot pieces of code the engine could provide a native implementation.\n\n## Import Semantics\n\nTo import modules from the standard library the engine has to be able to distinguish between standard library\nmodules and other (user defined) modules. To allow the engine to do this standard library modules will use a\nprefix in the module identifier string. This is prefered over other alternatives because it is does not\nintroduce new syntax for loading standard library modules and stays close to the `import` statement developers\nshould already be familiar with.\n\n### Namespace\n\nThe `js:` prefix will be reserved as the namespace for the JavaScript language only and will be governed by\nTC39, making the standard library a true JavaScript standard library. This will allow the committee to work\nsafely within this namespace when designing and developing the standard library over time.\n\n\u003e Alternatives for distinguishing standard modules are documented in [Appendix\n\u003e A](#a-distinguishing-standard-library-modules).\n\nBy creating a namespaces specifically for the JavaScript standard library, developers will know what to expect\nwhen importing from using the `js:` prefix across different implementations and can be assured the same\nmodules are available across these implementations (not considering implementation constraints, vendor\ntimelines or version differences).\n\nIt is completely feasable that more namespaces are introduced which are goverened by other standards bodies or\norganizations.  However it is important that these namespaces stay independent of each other to avoid\nconflicts, hamper development within namespaces due to outside pollution or time constraints due to\ndependencies on other organizations.\n\nThe namespace used for the JavaScript standard library will be registered with IANA to prevent collisions in\nthe future. Any other organization introducing a namespace prefix would be encouraged to do the same.\n\n### Freezing Exports\n\nAll exported objects and classes from the standard library will have their prototype frozen. This will prevent\nprototypes from imported objects to be modified outside of the module causing prototype pollution.\n\nIn the past the committee had to make concessions to maintain web compatibility when adding new functionality\nto built-in objects. By freezing the prototype of standard library exports, it will no longer be possible for \nthird party code to modify or extending library code in a possibly incompatible way. This will allow for more\nflexibility when designing and developing the standard library. Extending standard library classes and objects\ncan still be done using `extend` or `Object.create`.\n\nWe can start off by conventionally enforcing `Object.freeze` on exported Objects from standard library modules.\nIf this turns out to be hard to check and enforce a separate proposal can be created to describe automatically\nfreezing prototypes at the module boudary for standard library modules.\n\n*Note, the current direction is to freeze module contents thus requiring shimming code to wrap module classes and objects.  Given some discussion around this point, it may be dropped from the proposal before built in modulesa re added to the standard.*\n\n## Module Resolution\n\nTo allow the JavaScript engine to participate in module resolution and loading the\n**HostResolveModuleIdentifier** Abstract Operation should be changed to allow more than one resolver. The\nresolvers are arranged in a chain and consulted by the engine one by one to resolve a requested\nModuleIdentifier. This mechanism is heavily inspired by [Pythons importing system for\nmodules](https://docs.python.org/3/reference/import.html).\n\nThe implementation of the chain will be hidden inside the engine and will provide the same guarantees\n*HostResolveModuleIdentifier* currently does:\n\n* It must return an instance of ModuleRecord\n* It must throw an error if a ModuleRecord cannot be created\n* It must be idempotent for pair of (ModuleIdentifier, ReferencingModule)\n\nImporting is done in two phases: resolution and loading. Resolution is done through objects implementing the\n_ResolveModuleIdentifier_ operation and loading is done through objects implementing the\n_LoadModuleIdentifier_\noperation. Objects implementing both operations are referred to as importers.\n\n![Module Resolution and Loading Chain](module-resolution-and-loading-chain.png)\n\nMultiple importers can be registered with the engine and will be appended to the chain. The engine will always\nregister the internal JavaScript Standard Library importer first to make sure it is at the front of the chain.\n\nDuring the resolution step (phase 1) importers perform the _ResolveModuleIdentifier_ operation in order of\nregistration. This operation results in a _ModuleResolutionRecord_ that is passed along the chain and can be\nused by subsequent importers.\n\nAfter the resolution step the loading step (phase 2) is invoked. During this step the importers are visited in\nreverse order to perform the _LoadModuleIdentifier_ operation to try and load the requested _ModuleIdentifier_.\nThe operation is passed the _ModuleResolutionRecords_ from the resolution step. When the _ModuleIdentifier_ can be\nloaded a full _ModuleRecord_ is returned and the chain is exited immediately. When no _ModuleRecord_ is produced\nthe next importer is consulted until the chain is exhausted, resulting in a _ModuleNotFound_ error.\n\n### Shimming / Polyfilling\n\nDuring the loading step (phase 2) the chain is traversed in reverse order to allow for higher ranked (e.g.\nregistered later) importers to possibly override lower ranked importers. This will allow the host for example to\noverride standard library modules and achieve shimming / polyfilling.\n\nAlternatively, provisions are made for code to import a built-in module, shim it and update the host module table to point at the shimmed version.  This can be do repeatively so that shims / polyfills can be layored on top of each other.\n\nThere are three use cases that a polyfilling solution for the standard library should support:\n\n  * Add missing parts of the standard library\n  * Update incomplete implementations\n  * Redact parts of a library component.\n\n\u003e Polyfilling is intended to cover these three use cases only.\n\nFor the web platform polyfilling could be done using the [Import Maps Proposal](https://github.com/WICG/import-maps).\nA resolver registered by the embedder (a web browser in this case) could check the import map to see if a\nstandard library _ModuleIdentifier_ should be redirected to another implementation.\n\n\n## Related Efforts\n\nThis subject has been talked about in the past and has related efforts:\n\n- [https://github.com/tc39/ecma262/issues/395](https://github.com/tc39/ecma262/issues/395)\n- [https://github.com/WICG/import-maps](https://github.com/WICG/import-maps)\n\n## Frequently Asked Questions\n\n\u003e Coming Soon™\n\n## Appendices\n\n### A. Distinguishing Standard Library Modules\n\nOne of the requirements for the standard library is being able to distinguish when a module is user defined\nand when it should be loaded from the standard library. There are a lot of approaches to doing this and this\nsection contains alternatives considered to the recommendation earlier in the proposal.\n\n\u003e Important: The code samples and modules used in the examples are purely for illustrative purposes\n\n**Identifier Based**\n\nWhen importing a module the _ModuleSpecifier_ is required to be a string. Interpreting the contents of the\nstring is currently left to the embedder effectively always making it a user defined module.\n\nTo circumnavigate this and preserving the current behavior a different _ModuleSpecifier_ form using a special\n_Identifier_ could be used instead of a string literal:\n\n```js\nimport { ... } from std.SomeStandardModule;\n```\n\nThe `std` identifier is used to change the signature in a way that makes it possible for engines to detect\nthis is a module that should be loaded from the standard library. The downside of using `std.________` is that\nit start to look like a global object that is also available in other contexts.\n\nIt could also be possible to use specialized tokens in place of _Identifier_ prefix, for example similar to\nC/C++:\n\n```js\nimport { ... } from \u003cSomeStandardModule\u003e;\n```\n\nWhile this makes importing standard library modules  distinctly different from user defined modules this is\nalso one of the downsides. The syntax is different from the import syntax developers should already be\nfamiliar with and a dynamic variant would be difficult (gramar wise).\n\nNot using a prefix also has the downside of requiring everything from the standard library to live in the same\nspace creating a new “global” namespace and preventing the use of multiple namespaces for different contexts.\n\n\u003e Reference: [tc39/ecma262#395-comment-371865432](https://github.com/tc39/ecma262/issues/395#issuecomment-371865432)\n\n**Separate Keyword**\n\nWhen importing a module the _ModuleSpecifier_ is required to be a string. Interpreting the contents of the\nstring is currently left to the embedder effectively always making it a user defined module.\n\nTo circumnavigate this and preserving the current behavior a different keyword from `import` could be\nintroduced specifically for importing modules from the standard library:\n\n```js\ninclude { ... } from \u003cSomeStandardModule\u003e;\n```\n\n\u003e Important: The `include` keyword does not exist and is used for illustrative purposes only\n\nThe seperate keyword is emphasised by combining it with an Identifier for the _ModuleSpecifier_. The separate\nkeyword already distingishes the module enough so we can also safely use a string literal for the\n_ModuleSpecifier_:\n\n```js\ninclude { ... } from \"SomeStandardModule\";\n```\n\nWhile this makes importing standard library modules very distinctly different from user defined modules this\nis also one of its downsides. The syntax is different from the `import` syntax developers should already be\nfamiliar with and a dynamic variant of the keyword would also have to be created.\n\nNot using a prefix also has the downside of requiring everything from the standard library to live in the same\nspace creating a new “global” namespace and preventing the use of multiple namespaces for different contexts.\n\n\u003e Reference: [tc39/ecma262#395-comment-196917747](https://github.com/tc39/ecma262/issues/395#issuecomment-196917747)\n\n**URL Based**\n\nThere is already support for importing modules from a URL in browsers like Safari using `import`\nstatements inside of a `\u003cscript type=\"module\" ... /\u003e`. The host portion of the URL could be used as a prefix\nfor distinguishing standard library modules and fits very natural within the concept of URLs:\n\n```js\nimport { ... } from \"https://www.ecma-international.com/ecmascript/SomeStandardModule\";\n```\n\nUsing a URL with a domain for importing modules does not always make sense outside of a web context, for\nexample in Node.js or embedded devices. It also requires ownership of the domain over a long period of time.\nA transfer of the domain might make the prefix useless or exclude a number of modules from being imported.\n\n\u003e Reference: [tc39/ecma262#395-comment-328528910](https://github.com/tc39/ecma262/issues/395#issuecomment-328528910)\n\n**NPM Style**\n\nThe Node Package Manager (NPM for short) has an established format for importing packages published to a\ncentral registry. The format allows packages to be grouped under organizations and this could be leveraged as\na prefix for the JavaScript standard library:\n\n```js\nimport { ... } from \"@std/SomeStandardModule\";\n```\n\nWhile this format makes sense in environments where NPM is already used it is not as universal as a URL. The\nNPM style format also suffers some of the same downsides as a [**URL Based**](#url-based) approach.\n\nThis format would require ownership over the organization on NPM (https://npmjs.com) and keeping multiple\nnamespaces in mind would require all to do the same. But NPM is only the most commonly used registry, there\nmight be other registries, possibly private ones that would be impossible to get ownership over a\nnamespace. Using this format could exclude modules from being imported.\n\nThe biggest downside utilizing this format is standard library modules looking the same as user defined\nmodules which might cause confusion, for example where modules come from in a Node.js/NPM context. The two\nmodules behave different and the same assumptions can't be applied to both.\n\n\u003e Reference: [tc39/proposal-javascript-standard-library#16-comment-]()\n\n## Specification\n\n- [Ecmarkup source](https://github.com/tc39/proposal-built-in-modules/blob/master/spec.html)\n- [HTML version](https://tc39.es/proposal-built-in-modules/)\n\n## Implementations\n\n- none yet\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftc39%2Fproposal-built-in-modules","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftc39%2Fproposal-built-in-modules","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftc39%2Fproposal-built-in-modules/lists"}