{"id":19560013,"url":"https://github.com/plotdb/rescope","last_synced_at":"2026-03-02T14:40:09.950Z","repository":{"id":57137271,"uuid":"313343514","full_name":"plotdb/rescope","owner":"plotdb","description":"Load and scope any external JavaScript and reload scope on demand.","archived":false,"fork":false,"pushed_at":"2025-11-18T05:05:03.000Z","size":4127,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-11-18T05:36:49.323Z","etag":null,"topics":["javascript","module","scope"],"latest_commit_sha":null,"homepage":"http://plotdb.github.io/rescope/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/plotdb.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2020-11-16T15:21:05.000Z","updated_at":"2025-11-18T05:05:07.000Z","dependencies_parsed_at":"2024-03-26T09:24:42.000Z","dependency_job_id":"57392104-acf5-4585-805b-568f5103ea06","html_url":"https://github.com/plotdb/rescope","commit_stats":{"total_commits":141,"total_committers":1,"mean_commits":141.0,"dds":0.0,"last_synced_commit":"a583bae821154e4acb97a8fc99ab50beb9632d19"},"previous_names":[],"tags_count":58,"template":false,"template_full_name":null,"purl":"pkg:github/plotdb/rescope","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plotdb%2Frescope","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plotdb%2Frescope/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plotdb%2Frescope/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plotdb%2Frescope/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/plotdb","download_url":"https://codeload.github.com/plotdb/rescope/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plotdb%2Frescope/sbom","scorecard":{"id":738026,"data":{"date":"2025-08-11","repo":{"name":"github.com/plotdb/rescope","commit":"0d8c8e87a8ab88d56558128930f996c246523855"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":1.6,"checks":[{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"License","score":0,"reason":"license file not detected","details":["Warn: project does not have a license file"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact v5.0.15 not signed: https://api.github.com/repos/plotdb/rescope/releases/202581935","Warn: release artifact v5.0.14 not signed: https://api.github.com/repos/plotdb/rescope/releases/175832533","Warn: release artifact v5.0.13 not signed: https://api.github.com/repos/plotdb/rescope/releases/175821801","Warn: release artifact v5.0.12 not signed: https://api.github.com/repos/plotdb/rescope/releases/138774610","Warn: release artifact v5.0.11 not signed: https://api.github.com/repos/plotdb/rescope/releases/115713407","Warn: release artifact v5.0.15 does not have provenance: https://api.github.com/repos/plotdb/rescope/releases/202581935","Warn: release artifact v5.0.14 does not have provenance: https://api.github.com/repos/plotdb/rescope/releases/175832533","Warn: release artifact v5.0.13 does not have provenance: https://api.github.com/repos/plotdb/rescope/releases/175821801","Warn: release artifact v5.0.12 does not have provenance: https://api.github.com/repos/plotdb/rescope/releases/138774610","Warn: release artifact v5.0.11 does not have provenance: https://api.github.com/repos/plotdb/rescope/releases/115713407"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Vulnerabilities","score":4,"reason":"6 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-968p-4wvh-cqc8","Warn: Project is vulnerable to: GHSA-vc8w-jr9v-vj7f","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4","Warn: Project is vulnerable to: GHSA-h7cp-r72f-jxh6","Warn: Project is vulnerable to: GHSA-v62p-rq8g-8h59"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-22T16:29:06.650Z","repository_id":57137271,"created_at":"2025-08-22T16:29:06.650Z","updated_at":"2025-08-22T16:29:06.650Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30006766,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-02T14:08:50.421Z","status":"ssl_error","status_checked_at":"2026-03-02T14:08:50.037Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["javascript","module","scope"],"created_at":"2024-11-11T05:05:33.440Z","updated_at":"2026-03-02T14:40:09.940Z","avatar_url":"https://github.com/plotdb.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @plotdb/rescope\n\nLoad and scope any external JavaScript and reload scope on demand.\n\nFor example, assume here are the list of js url we'd like to load, which kept in `libs` variable:\n\n - assets/lib/bootstrap.native/main/bootstrap-native.min.js\n - assets/lib/bootstrap.ldui/main/bootstrap.ldui.min.js\n - assets/lib/@loadingio/ldquery/main/ldq.min.js\n - assets/lib/ldcover/main/ldcv.min.js\n - assets/lib/ldview/main/ldview.min.js\n\n\nWe can load all above js files with rescope, with a resolveed context containing all imported variables:\n\n    scope = new rescope!\n    scope.init!\n      .then -\u003e scope.load libs\n      .then (context) -\u003e myfunc(context)\n\n\nOnce loaded, we can access context for those libraries:\n\n    myfunc = -\u003e\n      scope.context libs, (context) -\u003e\n        {ldcover, ld$} = context\n        # now ldcover and ld$ are available ...\n        ldcv = new ldcover do\n          root: ld$.find('.ldcv', 0)\n\nThis is useful when you need the same library with different versions:\n\n    d3 = do\n      v3: 'https://d3js.org/d3.v3.min.js'\n      v6: 'https://d3js.org/d3.v6.min.js'\n\n    scope = new rescope!\n    scope.load d3.v6\n      .then -\u003e scope.load d3.v3\n      .then -\u003e scope.context d3.v6, ({d3}) -\u003e /* run v6 code with local d3 variable ... */\n      .then -\u003e scope.context d3.v3, ({d3}) -\u003e /* run v3 code with local d3 variable ... */\n\nWhile it's possible to load context into window object, we may run into trouble with concurrent overlapped context calls, so the context is always available as local variables. Always rely on the passed `context` object to access required libraries.\n\n\n## Semantic URL / Module Loading\n\nInstead of plain URLs, you can also request a library with its name, version and relative path. For example, \n\n    {url: \"assets/lib/@loadingio/ldquery/main/ldq.min.js\"}\n\ncan be represented as:\n\n    {name: \"@loadingio/ldquery\", version: \"main\", path: \"ldq.min.js\"}\n\nThis abstracts the location of libraries and thus can be customized if needed with `registry` option:\n\n    new rescope({registry: function(opt) {  return opt.name + opt.version + opt.path; });\n\nReturn promise from a registry function call for a directly content resolving - in this case you should return an object in following form:\n\n - `version`: exact version of the return object.\n - `content`: content for the requested resource.\n\n`registry` can also be an object with `url` and optionally `fetch` as a member function. Check `@plotdb/block` and `@plotdb/registry` for advanced registry usage.\n\n\nwhere registry, if provided, should be a function:\n\n - accepting an object with following members:\n   - `name`: module name\n   - `version`: module version\n   - `path`: relative path to the requested file\n - and return corresponding url based on those members, for example:\n   - `return [\"https://jsdelivr.net/npm\", opt.name, opt.version, opt.path].join('/');`\n\n\n## Customized Context\n\nLibraries can be loaded correctly in one single `load` invocation because `rescope` take care of the scope issue in `load` stage for us.\n\nHowever,\n\n - if we need `load` in separated stages, we may run into trouble of missing dependencies to libraries loaded earlier.\n - Additionally, we may want to load libraries into a specific context stored before.\n\nTo keep track of the context loaded , we pass an optional object directly into `load`:\n\n    scope.load libs, (ctx = {}) .then -\u003e ...\n\nonce loaded, the empty object `ctx` above will be filled with the loaded objects from libraries in `libs`. This `ctx` can then be used in turn in the following `load` calls:\n\n    ctx = {}\n    scope.load libs1, ctx\n      .then -\u003e scope.load libs2, ctx\n      .then -\u003e scope.load libs3, ctx\n      .then -\u003e ...\n\nin this manner, following libraries `libs2` and `libs3` can be loaded with the context of previous loaded libraries `libs1` without them being written in 1 load call.\n\n\n## Asynchronous Script Loading\n\nBy default all script are loaded asynchronously. You can force them loaded in synchronous manner, by extending URL into object with following options:\n\n - url: URL to load\n - async: load asynchronously if set to true. default true.\n\n\n## Delegate Window\n\nBy default `rescope` uses iframe window to preload libraries and peek variables they defined. The iframe is called delegate window. Apparently behavior for the host and the delegate is not the same.\n\nWe specify an option `delegate` and set it to false to tell `@plotdb/rescope` that this instance doesn't use delegate ( itself is a delegate ):\n\n    new rescope({delegate: false});\n\nAdditionally, you can also run code within delegate's context, by setting 'useDelegateLib' to `true`:\n\n    new resope({useDelegateLib: true})\n\nThis will only work when `delegate` is set to true ( which is by default ). With `useDelegateLib` set to true, all libraries loaded with the rescope object will work under a separated window and document object. Please note, it won't work as expected when cross refer libraries between two different global scope, so don't mix up libraries in different global scope.\n\nEven with `useDelegateLib` set to true, you can still enter host context by setting the second parameter to `false` when calling `context`:\n\n    res = new rescope({useDelegateLib: true});\n    res.context(\"some-lib\", false, function() { ... });\n\n## Caching\n\nInstead of downloading libraries everytime, you can also precache libraries into a single js file.\n\nAfter downloading all necessary libraries, get js for caching by:\n\n    ret = rescope.cacheDump();\n\nthe return value `ret` is the runnable JS string which insert cached libraries into `rescope` class. Or, manually inject cache by calling:\n\n    rescope.cache(\n      \"some-url\",\n      {\n        code: \"code\",\n        vars: [list of string for available variable names in dependency]\n      }\n    )\n\n## Bundling\n\nTo bundle, load `bundle.js` and use `bundle` API:\n\n    rsp = new rescop(...)\n    rsp.bundle [{ ... }] .then (code) -\u003e\n\n\n## Polyfills\n\nuse `prejs` when constructing for inserting pre-required JS into both host and delegate environment:\n\n    new rescope({prejs: [\"https://...\", ...]});\n\n\n\n## Note\n\n - This is not meant to be used for sandboxing or for security reason. `@plotdb/rescope` never prevent any scripts from accessing document, and all scripts are still run in the main thread.\n - some libraries such as `d3` may check and use object with the name they are going to use if exists. Thus we always have to restore context in case of disrupt their initialization process.\n - rescope mimics `window` object but there are still limitations. If a library declares a variable by `window.somevar` but accessing it with `somevar`, it will fail.\n\n\n## Limitation\n\nrescope uses proxy object to replace global objects such as `global`, `self`, `window` and `this`, so accessing `global` in library will actually be accessing the proxy object.\n\nHowever, there are still ways to get the actual window object, such as `window.parent` or `event.source`.\n\n\n### Event.source\n\n`event.source` in `message` event can be used to determine the source window of an event::\n\n    global.fire(\"message\", \"hello\");\n    global.on(\"message\", function(event) { event.source });\n\nSome libraries check `event.source` before using it like:\n\n    if(event.source == global) { ... }\n\nThis will fail since `event.source` (the real global) is not the same with `global` (the proxy object), since proxy object should never be equivalent to the proxied object.\n\nWe intercepte `event` to patch `source` by overriding `onmessage`, `addEventListener` and `removeEventListener`, however `onmessage` is native bridge and can't be run within proxy getter, so we solve it by adding a `queueMicrotask` in order to set `onmessage` in the correct realm, which introduced asynchronous behavior of onmessage. Since it's for messages which is also asynchronous actions, this won't cause too much trouble.\n\n\n### window.parent\n\nTBD\n\n\n## TODO\n\n - Browser compatibility check\n   - works in all major browsers ( latest Chrome, Firefox, Safari, Opera, Edge )\n   - doesn't work in IE11\n - Performance benchmark\n\n\n## Resources\n\n - ShadowRealm may help in what we want to do:\n   - https://github.com/tc39/proposal-shadowrealm/\n - Realm, predecessor of ShadowRealm\n   - Note: Realms proposal has been superceded by the ShadowRealm Proposal\n   - https://github.com/tc39/proposal-realms/#ecmascript-spec-proposal-for-realms-api\n   - https://github.com/Agoric/realms-shim\n     - based on their current statue: OBSOLETE, INSECURE, NOT RECOMMENDED FOR USE\n   - https://www.figma.com/blog/how-we-built-the-figma-plugin-system/\n - also check how Vue does its own scoping in template:\n   - https://github.com/vuejs/vue/blob/v2.6.10/src/core/instance/proxy.js#L9\n\n\n## License \n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fplotdb%2Frescope","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fplotdb%2Frescope","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fplotdb%2Frescope/lists"}