{"id":20476386,"url":"https://github.com/thoughtspile/scoped-function","last_synced_at":"2025-04-13T12:34:48.560Z","repository":{"id":81064603,"uuid":"137059865","full_name":"thoughtspile/scoped-function","owner":"thoughtspile","description":"ScopedFunction = new Function + scope","archived":false,"fork":false,"pushed_at":"2018-06-12T11:46:24.000Z","size":11,"stargazers_count":9,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-27T03:41:30.359Z","etag":null,"topics":["compiler","dsl","function","javascript","metaprogramming","utility"],"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/thoughtspile.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-06-12T11:06:09.000Z","updated_at":"2023-07-27T12:03:59.000Z","dependencies_parsed_at":"2023-06-11T18:45:12.078Z","dependency_job_id":null,"html_url":"https://github.com/thoughtspile/scoped-function","commit_stats":{"total_commits":10,"total_committers":1,"mean_commits":10.0,"dds":0.0,"last_synced_commit":"897ea6df904a70d94cd4955b2622c967dd516916"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thoughtspile%2Fscoped-function","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thoughtspile%2Fscoped-function/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thoughtspile%2Fscoped-function/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thoughtspile%2Fscoped-function/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thoughtspile","download_url":"https://codeload.github.com/thoughtspile/scoped-function/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248714754,"owners_count":21149961,"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":["compiler","dsl","function","javascript","metaprogramming","utility"],"created_at":"2024-11-15T15:20:19.243Z","updated_at":"2025-04-13T12:34:48.542Z","avatar_url":"https://github.com/thoughtspile.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ScopedFunction = new Function + scope\n\n`ScopedFunction` allows you to inject scope object into `Function` constructor.\nThe properties of the scope object can be accesed in the function body as if they\nwere closure variables: `ScopedFunction('return s;', { s: 'hello' }) -\u003e 'hello'`.\n\nBuild paper-thin DSLs over JavaScript syntax — let your users write math in\nstandard syntax, `exp(10 * cos(x))`, without prepending the nasty `Math`\nbuiltin, or pass libraries to in-browser JS playgrounds.\n\nThere's no runtime performance penalty for functions compiled using `ScopedFunction`.\nThis library is a great foundation for safer and faster `eval` or `with`, the\ninfamous optimization busters. `ScopedFunction` is tiny: \u003c40 SLOC, or around\n500 bytes minified.\n\n## Usage\n\n```js\n// Use whichever you like\nconst ScopedFunction = require('ScopedFunction');\nimport ScopedFunction from 'scoped-function';\n// You can also drop lib/scoped-function.js into your HTML if you feel like it\n\n// Build your smallest DSL ever:\nconst trig = ScopedFunction('x', 'return sin(pi * x) + cos(pi * x)', {\n  sin: Math.sin,\n  cos: Math.cos,\n  pi: Math.PI\n});\nconst v = trig(1); // = -1\n\n// Add slight rewriting:\nconst compileMath = e =\u003e ScopedFunction('x', `return (${e});`, Math);\ncompileMath('atan(exp(x) - 1)')(0); // = 0\n\n// Inject libraries into user code\n// Say you're building a JS course with live problems:\nconst userSolution = `\nfunction ageMode(data) {\n  if (_.isEmpty(data)) return undefined;\n  return _.maxBy(\n    _.values(_.groupBy(data, 'age')),\n    v =\u003e v.length\n  )[0].age;\n}\n`;\nconst _ = require('lodash');\n// Note return + call: we can't parse the user-supplied function, but still inject the \"_\"\nconst userFn = ScopedFunction(`return (${userSolution});`, { _ })();\nconst isValid = userFn([{ age: 10 }, { age: 20 }, { age: 10 }]) === 10;\n\n// You can also use ScopedFunction as a constructor:\nconst f = new ScopedFunction('x', 'return _.min(x)', { _ });\n```\n\n## Standards Compliance and Usage Notes\n\n`ScopedFunction` shallow-clones the scope object — you can't add, remove, or change\nthe variables afterwards. However, the objects (as in `{ hub: {} }`) are shared\nby reference. Use this to communicate between the functions, or opt out with\na `_.cloneDeep(...)`.\n\nThe functions produced mimic the ones that come from `Function(...)`:\n\n - respond to `typeof` / `instanceof`\n - have proper `call` / `bind` / `apply`\n - accessing `arguments` still works\n - name is set to `anonymous` as per the spec.\n\nIf you find a deviation from the [spec](https://www.ecma-international.org/ecma-262/6.0/#sec-function-constructor), drop an issue.\n\nBoth `Function` and `ScopedFunction` accept non-simple ES6 formal\nparameters: `...rest`, `{ destructuring }`, and `default = true`. Use these in\nthe browser, but remember that your code is compiled as-is, not transpiled,\nand would break in browsers with poor ES6 support, like Safari.\n\nAlso note that this library does not give you a secure sanbox for untrusted code\n— use [vm2](https://github.com/patriksimek/vm2) for that.\n\n## Installation\n```sh\n$ npm i --save scoped-function\n$ yarn add scoped-function\n```\n\nMade by [Vladimir Klepov](https://github.com/thoughtspile).\n\n## License\n\n[MIT](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthoughtspile%2Fscoped-function","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthoughtspile%2Fscoped-function","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthoughtspile%2Fscoped-function/lists"}