{"id":27642013,"url":"https://github.com/bathos/rollup-plugin-realm-uri","last_synced_at":"2025-04-23T23:52:10.127Z","repository":{"id":53146996,"uuid":"191504491","full_name":"bathos/rollup-plugin-realm-uri","owner":"bathos","description":"back on my bullshit","archived":false,"fork":false,"pushed_at":"2023-03-04T03:54:31.000Z","size":292,"stargazers_count":3,"open_issues_count":3,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-23T23:52:06.048Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bathos.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}},"created_at":"2019-06-12T05:37:44.000Z","updated_at":"2021-04-04T14:56:48.000Z","dependencies_parsed_at":"2023-02-06T11:31:02.095Z","dependency_job_id":null,"html_url":"https://github.com/bathos/rollup-plugin-realm-uri","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bathos%2Frollup-plugin-realm-uri","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bathos%2Frollup-plugin-realm-uri/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bathos%2Frollup-plugin-realm-uri/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bathos%2Frollup-plugin-realm-uri/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bathos","download_url":"https://codeload.github.com/bathos/rollup-plugin-realm-uri/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250535081,"owners_count":21446506,"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":"2025-04-23T23:52:09.529Z","updated_at":"2025-04-23T23:52:10.111Z","avatar_url":"https://github.com/bathos.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Rollup Plugin ‘Realm URI’\n\nThis [Rollup][rollup] plugin adds support for ES import specifiers that use a\n`realm:` scheme URI to allow importing deduplicated, fixed references to global\nvalues within the current realm.\n\n## Changes\n\n### 2.0.0:\n\n- Meta: No longer generating a CJS entrypoint in dist\n- Meta: Now exporting an `esbuild()` adapter function\n- Bug fix: Importing the `realm:ArrayIteratorPrototype/` context now works\n- Behavior: `#g` and `#s` now pick up inherited accessors\n- Behavior: `#g` and `#s` will now return undefined if LHS is nullish\n- Behavior: the `t=i`, `t=b`, and `t=n` transforms do the same\n\n\u003e A summary of the main change here: apart from those using `#d`, realm URI\n\u003e imports are now forgiving of intermediate members which are null or undefined.\n\u003e Nullish values will pass through as undefined even if there’s a transform\n\u003e applied.\n\u003e\n\u003e This makes realm URIs more flexible for scenarios where you’re interested in\n\u003e built-in values which may not be present, e.g. due to `Window` vs `Worker`,\n\u003e `[SecureContext]`, or when using newer APIs that aren’t available everywhere.\n\n\u003c!-- MarkdownTOC autolink=true --\u003e\n\n- [Usage example](#usage-example)\n- [When is this useful?](#when-is-this-useful)\n- [How do realm URIs help?](#how-do-realm-uris-help)\n- [Realm URIs](#realm-uris)\n  - [Pathname](#pathname)\n    - [Context](#context)\n    - [Property path](#property-path)\n  - [Query](#query)\n    - [Transform: Invert](#transform-invert)\n    - [Transform: Bind](#transform-bind)\n    - [Other transforms](#other-transforms)\n  - [Fragment](#fragment)\n  - [Percent-encoding](#percent-encoding)\n  - [Valid combinations](#valid-combinations)\n- [Additional considerations](#additional-considerations)\n\n\u003c!-- /MarkdownTOC --\u003e\n\n## Usage example\n\nIn the following module, you want to use `find`, but you don’t trust the env to\nleave intrinsics alone. Or perhaps this function wants to accept any array-like,\nnot limited to arrays:\n\n```js\nimport find from 'realm:Array.prototype.find?t=invert';\n\nexport function getFoo(arr) {\n  return find(arr, member =\u003e member.id === 'foo');\n}\n```\n\nYour rollup config for this might look like so:\n\n```js\nimport rollupPluginRealmURI from 'rollup-plugin-realm-uri';\n\nexport default {\n  input: 'src/index.mjs',\n  output: { format: 'esm', file: 'dist/index.mjs' },\n  plugins: [ rollupPluginRealmURI() ]\n};\n```\n\nOr, using esbuild:\n\n```js\nimport * as realmURIPlugin from 'rollup-plugin-realm-uri';\n\nesbuild.build({\n  bundle: true,\n  entryPoints: [ 'src/index.mjs' ],\n  format: 'esm',\n  outfile: 'dist/index.mjs',\n  plugins: [ realmURIPlugin.esbuild() ],\n  target: 'esnext'\n});\n\n```\n\n## When is this useful?\n\nRealm URIs try to address some of the awkwardness of authoring highly defensive\nJavaScript. We should first explore ‘when is it worthwhile to write defensive\nJavaScript?’, then look at how realm URIs may help with that. For that matter,\nwe should probably start by clarifying what’s meant by ‘defensive’ here.\n\n‘Defensive code’ can mean several things. Here, it’s something pretty specific:\ncode that aims to reduce the ‘assumption surface area’ regarding globally\nmutable state. While many dynamic languages have shared global state, this can\nbe particularly challenging in JS.\n\nTypically, if we want to use `Date`, we just type `Date`. It’s already in scope\n— it’s a global. Likewise for `Object.keys` and many others. We also call\ninherited built-in methods all the time — `myArray.forEach`, say. Those methods\nare global too, just not in all the same senses.\n\nWhen we do this, we’re making assumptions about global state that is actually\nmutable (unless we’ve [frozen the realm][frozen-realms] or are inside certain\nkinds of [secure sandboxes][ses]). Usually when we talk about ‘global state,’\nwe’re only to referring to globally-scoped variables introduced by our\napplication code. However there’s no essential difference between these and the\nintrinsics defined by ECMAScript itself (or HTML, etc).\n\nThere are good reasons to pretend there is a difference, though. It’s generally\nimpractical and counterproductive to worry about the global mutable state of\nbuiltins. We accept the fiction that code relying on global state has defined\nbehavior (sometimes even labeling it ‘pure’) because giving it defined behavior\ntakes a lot of extra work, makes the code less approachable, and typically will\nnot produce significant (or any) benefit. Instead, we have a sanity-preserving\nrule for human beings: ‘no one should alter intrinsics except to (accurately)\npolyfill’. It’s a caveat emptor, really. If someone writes nonsense like, say,\n`Array.prototype.map = console.log`, then opens a GitHub issue on a library\ncomplaining that the library wasn’t robust enough to handle this ... well, it’s\na pretty safe bet that the issue will get closed with `wontfix` and one to four\nlaughing-face emoji.\n\nEven if we might consider these circumstances suboptimal, it seems to work out\nalright almost always. So what conditions might make the caveat emptor\ninadequate? The most perfect example is occurs in the context of adblocking\nextensions. Adblockers are in an arms race with other code in the same (or\nconnected) realms to control certain facets of the environment — while remaining\nundetected. Every assumption the adblocker makes about global state could become\nan opportunity for anti-adblocking code to compromise the adblocker. Instead of\ncode that wants to work together, here we’re looking at two applications in an\nadversarial relationship running in a shared environment. A ‘you just shouldn’t\ndo that’ golden rule means nothing here.\n\nThere are less extreme scenarios where defensiveness about global state may also\nbe worthwhile. Polyfills, which often aim to be spec compliant implementations\nto whatever extent is possible, are another place you’re apt to find it. The\ninternal operations of native implementations are never affected by the state of\nthe ES realm, so a high fidelity polyfill would not be, either. Since polyfills\nare generally narrow in scope, the extra effort involved in this defensiveness\ntends to stay manageable and justifiable.\n\nMore generally, libraries which will be used on many uncontrolled websites may\nwish to take on some measure of defensiveness. It may be targeted, addressing\nonly well-known hauntings like MooTools. Effective defensive code may benefit\nfrom entering a mindset where other code is presumed to be adversarial, but this\nshouldn’t be mistaken for ascribing real-world malicious intent. Almost all\nrealm poisoning occuring in nature is well-intentioned or historical and just\nhappens to break our expectations today. If you’re authoring shared widgets\nlike, say, the Twitter embed, whose audience will include people with limited\ndevelopment experience on Wordpress sites that load seven different instances of\njQuery per page, ‘don’t you know you shouldn’t do that?’ is neither realistic\nnor fair to your users. There’s some really wild shit out there, but there isn’t\nalways somebody around who can fix it.\n\nI’ve mentioned or implied a few times that defensive JS has a cost. It’s a\npretty high cost. It influences how code is written in deep ways — you have to\npay attention to things that are normally treated as implementation details. The\ncode will become less idiomatic, sometimes downright strange. The potential\nbenefits in a given case must be weighed against the downside of a codebase\nwhich may become harder to understand and which requires some less-common domain\nexpertise to be maintained.\n\n\u003cdetails\u003e\n  \u003csummary\u003e❔ \u003cem\u003eWhy do you, author, care about this?\u003c/em\u003e\u003c/summary\u003e\n\n\u003e \u0026nbsp;\n\u003e\n\u003e Mainly curiosity, which I think began when I worked at [Wistia][wistia]. The\n\u003e Wistia video player is used on a ton of websites. Occasionally, a bug\n\u003e investigation would reveal the root cause was one of our innocent looking\n\u003e environmental assumptions being invalidated by realm poisoning. Sometimes\n\u003e these issues can be totally unique to one website — it’s not always due to old\n\u003e toolbelt libs. People are very creative! Those sorts of bugs are hard to trace\n\u003e (especially since you’re looking at somebody else’s production site), and I\n\u003e wondered whether there were generalizable mitigation strategies that could\n\u003e improve the odds of a library trudging right through a JavaScript Bosch\n\u003e painting unfazed.\n\u003e\n\u003e I’m also an insufferable extensible-web nutcase, so anything that helps bring\n\u003e ES-authored APIs to parity with native implementations pushes my buttons.\n\u003e Ultimately, though, I just think it’s an interesting problem space.\n\n\u003c/details\u003e\n\n## How do realm URIs help?\n\nThe most common tool for mitigating against global mutation affecting your code\nis capturing references to intrinsic values at module or script evaluation time\ninstead of dynamically accessing them later on.\n\n\u003e It’s impossible to eliminate assumptions about global state while also\n\u003e availing ourselves of built-in platform functionality — some of which will be\n\u003e the only place that primitive functionality exists. For example, the primitive\n\u003e building blocks for weak associations live in WeakSet and WeakMap’s (mutable)\n\u003e APIs. Short of reimplementing JS and its garbage collection in the JS layer,\n\u003e we cannot make use of weak associations without touching those APIs at least\n\u003e once.\n\nConsider the following two similar modules:\n\n```js\nexport function isSafeInteger(value) {\n  return (\n    Number.isInteger(value) \u0026\u0026\n    value \u003e= Number.MIN_SAFE_INTEGER \u0026\u0026\n    value \u003c= Number.MAX_SAFE_INTEGER\n  );\n}\n```\n\n```js\nconst { isInteger, MIN_SAFE_INTEGER, MAX_SAFE_INTEGER } = Number;\n\nexport function isSafeInteger(value) {\n  return (\n    isInteger(value) \u0026\u0026\n    value \u003e= MIN_SAFE_INTEGER \u0026\u0026\n    value \u003c= MAX_SAFE_INTEGER\n  );\n}\n```\n\nBoth of these modules expect Number to be defined, and both expect it to have\nthree properties with particular values. The difference is not the assumptions\nthemselves, but rather their scope. The former module makes these assumptions\nagain every time the `isSafeInteger` function is invoked, while the latter only\nmakes the assumptions once, at module evaluation time.\n\nRealm URIs provide a way to import intrinsics like these, deduplicating the\n‘capture statements’ that might end up repeated many times otherwise.\n\n```js\nimport isInteger from 'realm:Number.isInteger';\n```\n\nEach module that uses `isInteger` will point at a single module that performs\nthe property access once during initial evaluation. But this example doesn’t\nshow us much — to be honest, the import isn’t much of an improvement here. Where\nthings get interesting is _methods._\n\nAvoiding dynamic property access after initial evaluation is not usually as\nsimple as in the above example. Methods and accessors introduce the most common\ncomplication:\n\n```js\nconst { slice } = Array.prototype;\n\n// How to use slice? If we do slice.call(), we’re only moving the problem\n// around, since now we’re dynamically accessing Function.prototype.call.\n```\n\nTo address this, realm URIs may include a query parameter, `transform=invert`,\nwhich requests a new version of the target method which takes the receiver\n(`this`) as its first argument. Transform queries have shorthand because they\nare needed frequently.\n\n```js\nimport slice from 'realm:Array.prototype.slice?t=i';\n\nslice([ 1, 2, 3 ], 1); // [ 2, 3 ]\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003e❔ \u003cem\u003eHow does invert work?\u003c/em\u003e\u003c/summary\u003e\n\n\u003e \u0026nbsp;\n\u003e\n\u003e Invert uses `Reflect.apply` (captured) to invoke the wrapped function with a\n\u003e specific receiver (`this` arg) without using property lookup. Doing this\n\u003e directly in your code adds a lot of noisy boilerplate, so the declarative\n\u003e wrapping can help a lot.\n\u003e\n\u003e Both `Reflect.apply` and `Function.prototype.apply` take an argument that\n\u003e represents the arguments to invoke the target function with. The astute\n\u003e paranoiac may wonder if this is safe — won’t `@@iterator` and `next` be\n\u003e called? Fortunately, both of these methods accept an arraylike, not an\n\u003e iterable, and array index keyed properties and the length property of an array\n\u003e exotic object are reliable in this context.\n\n\u003c/details\u003e\n\nJS written without methods may tend to end up looking lispy. Methods that would\ntypically be chained end up nested instead: `foo.bar().baz().qux()` becomes\n`qux(baz(bar(foo)))`. The usual order can still be had if you perform a series\nof assignments instead of nesting, but if you happen to be playing around with\nthe pipeline operator proposal, you might actually consider this an ergonomic\nenhancement. Generally, methodless JS plays a little nicer with functional\nprogramming patterns.\n\n\u003e Aside from its inadvertent friendliness towards functional programming,\n\u003e another incidental benefit is that it tends to increase opportunities for name\n\u003e mangling during minification. Even after compression, name mangling is\n\u003e typically the most effective minification technique. In code that makes heavy,\n\u003e repeated use of builtin APIs, the difference is sometimes pretty significant.\n\n---\n\nThe sum effect of using realm URIs in defensive code is that they help reduce\nboilerplate, avoid bloat, and bring a bit of consistency to what may tend to end\nup feeling like a pretty messy set of concerns.\n\nHaving looked at examples of the core functionality, we can now dig into the\nrealm URI grammar and what each part of the URI means.\n\n## Realm URIs\n\nJust to be clear: the `realm:` scheme is not a formally registered URI scheme.\nIt is defined here and implemented only by this library.\n\nRealm scheme URIs conform to the [URL specification][url]. They are\n[non-special][special-scheme] and they do not have username, password, hostname,\nor port, but they do have pathname, fragment, and query portions.\n\n### Pathname\n\nThe pathname consists of two parts: the _context_ and the _path_.\n\n#### Context\n\nThe context determines the base (leftmost) value of the virtual member\nexpression which the URI describes.\n\nThe examples we have seen so far omitted an explicit context. The default,\n`globalThis`, is usually what you want. However there is some intrinsic global\nstate which cannot be reached from `globalThis` (or which can only be reached\nusing Annex B properties) and that’s where explicit contexts come in.\n\nA context is an identifier followed by one slash.\n\n```js\nimport next from 'realm:ArrayIteratorPrototype/next';\n```\n\nThere are currently 19 possible context values. Aside from `globalThis`, their\nnames can be found in the list of [well-known intrinsic objects][wkio]\\*.\nSpecifically, they are the rows in that table where the ‘global name’ cells are\nblank. When used in a realm URI, the delimiting percent signs (which would\ncollide with URI percent encoding) are omitted.\n\n\u003e \\* Presently `%RegExpStringIteratorPrototype%` is missing from the list but I\n\u003e believe this is accidental.\n\n#### Property path\n\nThe rest of the pathname is the (property) path, which resembles a member\nexpression. Segments may be ES identifiers (bare), prefixed with a period except\nin initial position, or they may use a bracket notation for describing both\nstring and symbol keys (well-known or global).\n\nMultiple representations may exist for a single URI pointing at a single module:\n\n```js\nimport createA from 'realm:Object.create';\nimport createB from 'realm:[\"Object\"][\"create\"]';\nimport createC from 'realm:Object.creat%65';\n\nassert(createA === createB);\nassert(createA === createC);\n\n// Okay, not a good demo of the fact that they’re all the same module instance\n// and not three that export the same value, but you get the idea.\n```\n\nThe canonical representation is the shortest representation. If the canonical\npath, query, and fragment are the same, they are understood to point at the same\nmodule. Paths describing different properties are distinct, even if they happen\nto point at the same value. For example, \"realm:Object\" and \"realm:constructor\"\nare different modules.\n\nStrings are double-quote delimited. Well-known symbols use `@@identifier`\nnotation, where `identifier` is the property name by which the well-known symbol\nis exposed on `Symbol`. Global symbols use `@@\"string\"` notation.\n\n```js\nimport values from 'realm:Array.prototype[@@iterator]';\nimport inspectURL from 'realm:URL.prototype[@@\"nodejs.util.inspect.custom\"]';\n```\n\nThe property path can be empty. In this case, the URI is addressing the context\ndirectly. Since the context part is also optional, the URI `realm:` is valid:\n`import globalThis from 'realm:';`.\n\n\u003cdetails\u003e\n  \u003csummary\u003e❔ \u003cem\u003eWhat is a well-known or global symbol?\u003c/em\u003e\u003c/summary\u003e\n\n\u003e \u0026nbsp;\n\u003e\n\u003e A well-known symbol is one defined by ES proper, like `Symbol.iterator`. A\n\u003e global symbol is one accessed through `Symbol.for(string)`. In both cases,\n\u003e these symbols can be generically serialized — the former because the name to\n\u003e value mapping is defined by ES and the latter because the string is sufficient\n\u003e for obtaining the symbol in any realm. Symbols created with `Symbol()`,\n\u003e however, are not generically serializable and can’t be expressed in URIs.\n\n\u003c/details\u003e\n\n### Query\n\nThe query portion of the URI currently supports a single parameter, `transform`.\n\n| parameter            | short | target      | wat                             |\n|----------------------|-------|-------------|---------------------------------|\n| `transform=bind`     | `t=b` | method      | bind receiver to LHS            |\n| `transform=invert`   | `t=i` | method      | unshift receiver into signature |\n| `transform=none`     | `t=n` | any         | value as-is                     |\n\nWhether a given tranformation is applicable depends on the nature of the target\nof the URI, which is generally not something known until runtime. The default\nis ‘none’. We’ll now look at what each transformation does, starting with the\nmost useful item, `invert`.\n\n#### Transform: Invert\n\nThe ‘invert’ transformation takes a method and returns a non-method function.\nThe new function accepts the would-be receiver (`this` value) as its first\nargument:\n\n```js\nimport pop from 'realm:Array.prototype.pop?t=invert';\n\npop([ 3, 4 ]); // 4\n```\n\n#### Transform: Bind\n\nThe bind transformation is only occasionally useful. It is mainly helpful for\nstatic methods which are receiver-sensitive, like those of `Promise`, or for\ninstance methods which you may want to associate with an existing singleton\ninstance. Consider the following module using ‘invert’:\n\n```js\nimport Promise from 'realm:Promise';\nimport createElement from 'realm:Document.prototype.createElement?t=i';\nimport document from 'realm:document';\nimport resolve from 'realm:Promise.resolve?t=i';\n\nconst promise = resolve(Promise, createElement(document, 'marquee'));\n```\n\nIn practice, it’s very likely that we always want to use `Promise` as the\nreceiver for `resolve`, and perhaps we know we always want to create elements\nusing the local document instance. We can simplify this using `bind`, then:\n\n```js\nimport resolve from 'realm:Promise.resolve?t=bind';\nimport createElement from 'realm:document.createElement?t=bind';\n\nconst promise = resolve(createElement('marquee'));\n```\n\n#### Other transforms\n\nI’ve experimented with a third transform, ‘snapshot’, intended for constructors.\nThe snapshot transform would return a new class with a cloned, flattened\ninterface, allowing (potentially) safe use of ordinary methods, provided the\nsnapshot instances are used only internally. This approach is effective for\nArray (because of @@species) and RegExp (because of ... everything). But there\nare caveats, especially for userland classes. The constraints are complex and\nchallenging to communicate, so I haven’t felt it is suitable for inclusion yet.\n\n### Fragment\n\nThe fragment portion of the URI must be, if present, one of the following:\n\n| fragment      | short | meaning                                              |\n|---------------|-------|------------------------------------------------------|\n| `#descriptor` | `#d`  | target is the property descriptor                    |\n| `#get`        | `#g`  | target is `get` function of the property descriptor  |\n| `#set`        | `#s`  | target is `set` function of the property descriptor  |\n| `#value`      | `#v`  | target is the property value (retrieved with Get())  |\n\nThe default is `#value`. The property may be inherited by the lefthand side\nobject rather than its own property except when the `#descriptor` fragment is\nused.\n\nAccessor get/set functions are effectively methods, just exposed through a\ndifferent API, so they are suitable for use with the `invert` transform.\n\n```js\nimport getSetSize from 'realm:Set.prototype.size?t=i#get';\n\ngetSetSize(new Set('abc')); // 3\n```\n\n### Percent-encoding\n\nPercent-encoded bytes describing valid UTF-8 code unit sequences are legal in\nRealm URIs, but as in other URIs, only to represent values that aren’t syntactic\nconstructs in the realm URI grammar. Depending on context, realm URIs consider\nperiods, brackets, at-signs, and double quotes to be syntactic where an HTTP URL\nwould not. For example, `realm:%41rray.of` is valid while `realm:Array%2Eof`\nisn’t.\n\nThe realm URI grammar must be a subset of the URL grammar. This means that a \"?\"\nor \"#\" terminates the pathname portion of a URI even if it occurs within\nbrackets or quotes. These characters must be percent-encoded.\n\n### Valid combinations\n\nCertain combinations of transforms, targets, and paths are not valid, but it\nwill probably be apparent why. For example, you cannot use `invert` with\n`descriptor` because we know that a descriptor target will never be a function.\nWhere it’s possible for us to know that a combination is invalid statically, an\nerror will be thrown at compilation time.\n\n## Additional considerations\n\nThe realm URI scheme aims to make writing defensive JS more comfortable, but\nusing it does not instantly make code ‘safer’. There are many additional\nconsiderations when avoiding sensitivity to realm mutation which are not\naddressed at all here. Ultimately you have to know exactly what a function is\ndoing to be able to say whether it’s safe. Some intrinsics require special\nwrapping or custom reimplementation to patch the holes.\n\n---\n\n[frozen-realms]:\n  https://github.com/tc39/proposal-frozen-realms/\n  \"Frozen Realms EcmaScript proposal\"\n\n[rollup]:\n  https://rollupjs.org/guide/en/\n  \"Rollup.js\"\n\n[ses]:\n  https://github.com/Agoric/SES\n  \"SES (Secure EcmaScript)\"\n\n[special-scheme]:\n  https://url.spec.whatwg.org/#special-scheme\n  \"URL miscellaneous: special scheme\"\n\n[url]:\n  https://url.spec.whatwg.org/\n  \"URL Living Standard (WHATWG)\"\n\n[wistia]:\n  https://wistia.com/support/player\n  \"Wistia Player\"\n\n[wkio]:\n  https://tc39.es/ecma262/#sec-well-known-intrinsic-objects\n  \"ECMA 262: Well-Known Intrinsic Objects\"\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbathos%2Frollup-plugin-realm-uri","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbathos%2Frollup-plugin-realm-uri","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbathos%2Frollup-plugin-realm-uri/lists"}