Skip to content

Commit

Permalink
feat(endomoat): support native modules in policy generation [ci skip]
Browse files Browse the repository at this point in the history
# Conflicts:
#	packages/endomoat/src/policy-gen/policy-generator-context.js
  • Loading branch information
boneskull committed Mar 26, 2024
1 parent be24431 commit 5c30580
Show file tree
Hide file tree
Showing 38 changed files with 833 additions and 10 deletions.
10 changes: 10 additions & 0 deletions packages/endomoat/src/constants.js
Expand Up @@ -65,3 +65,13 @@ export const LMR_TYPE_BUILTIN = 'builtin'
* `js` module type for a `LavamoatModuleRecord`
*/
export const LMR_TYPE_SOURCE = 'js'

/**
* `native` module type for a `LavamoatModuleRecord`
*/
export const LMR_TYPE_NATIVE = 'native'

/**
* Name of Endo's `bytes` parser
*/
export const ENDO_PARSER_BYTES = 'bytes'
30 changes: 21 additions & 9 deletions packages/endomoat/src/policy-gen/policy-generator-context.js
Expand Up @@ -8,8 +8,10 @@ import { isBuiltin as nodeIsBuiltin } from 'node:module'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import {
ENDO_PARSER_BYTES,
LAVAMOAT_PKG_POLICY_ROOT,
LMR_TYPE_BUILTIN,
LMR_TYPE_NATIVE,
LMR_TYPE_SOURCE,
} from '../constants.js'
import { defaultReadPowers } from '../power.js'
Expand Down Expand Up @@ -289,7 +291,10 @@ export class PolicyGeneratorContext {
* @returns {Promise<import('lavamoat-core').LavamoatModuleRecord[]>}
* @internal
*/
async buildModuleRecordsForSource(specifier, { record, sourceLocation }) {
async buildModuleRecordsForSource(
specifier,
{ parser, record, sourceLocation }
) {
if (!sourceLocation) {
// XXX: why would we not have a sourceLocation?
throw new TypeError(
Expand Down Expand Up @@ -317,17 +322,24 @@ export class PolicyGeneratorContext {
* The `ModuleSource.content` prop is already pre-processed by Endo, and we
* do not want that, since it befouls our AST crawling.
*
* This will not be run if the `parser` is `bytes`.
*
* @remarks
* Doing this first since it may be more likely to fail than the other
* operations below
* @type {NonNullable<
* import('lavamoat-core').LavamoatModuleRecord['content']
* >}
* operations below.
* @type {string | undefined}
* @todo Modify Endo to surface the original source
*
* @todo Add more exceptions to the parsers?
*/
const content = await this.#readPowers
.read(sourceLocation)
.then((buffer) => PolicyGeneratorContext.#decoder.decode(buffer))
let content

await Promise.resolve()
if (parser !== ENDO_PARSER_BYTES) {
content = await this.#readPowers
.read(sourceLocation)
.then((buffer) => PolicyGeneratorContext.#decoder.decode(buffer))
}

/**
* The {@link LavamoatModuleRecord.file} prop
Expand Down Expand Up @@ -356,7 +368,7 @@ export class PolicyGeneratorContext {
packageName: this.packageName,
importMap,
content,
type: LMR_TYPE_SOURCE,
type: parser === ENDO_PARSER_BYTES ? LMR_TYPE_NATIVE : LMR_TYPE_SOURCE,
}),
]

Expand Down
5 changes: 5 additions & 0 deletions packages/endomoat/test/fixture/dynamic/README.md
@@ -0,0 +1,5 @@
This fixture is not used directly; it's only here in order to create a snapshot:

```bash
npm run start
```
2 changes: 2 additions & 0 deletions packages/endomoat/test/fixture/dynamic/index.js
@@ -0,0 +1,2 @@
import addon from 'hello_world'
export const hello = addon.hello()

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions packages/endomoat/test/fixture/dynamic/package.json
@@ -0,0 +1,14 @@
{
"name": "hello",
"version": "0.0.0",
"type": "module",
"description": "this code actually runs",
"private": true,
"main": "index.js",
"scripts": {
"start": "npx snapshot-fs . ../json/dynamic.json"
},
"dependencies": {
"hello_world": "0.0.0"
}
}
12 changes: 12 additions & 0 deletions packages/endomoat/test/fixture/json/dynamic.json
@@ -0,0 +1,12 @@
{
"/package.json": "{\n \"name\": \"hello\",\n \"version\": \"0.0.0\",\n \"type\": \"module\",\n \"description\": \"this code actually runs\",\n \"private\": true,\n \"main\": \"index.js\",\n \"scripts\": {\n \"start\": \"npx snapshot-fs . ../json/dynamic.json\"\n },\n \"dependencies\": {\n \"hello_world\": \"0.0.0\"\n }\n}\n",
"/index.js": "import addon from 'hello_world'\nexport const hello = addon.hello()\n",
"/README.md": "This fixture is not used directly; it's only here in order to create a snapshot:\n\n```bash\nnpm run start\n```\n",
"/node_modules/hello_world/world.js": "export default 'world';\n",
"/node_modules/hello_world/package.json": "{\n \"name\": \"hello_world\",\n \"version\": \"0.0.0\",\n \"description\": \"Node.js Addons Example #1\",\n \"main\": \"hello.js\",\n \"type\": \"module\",\n \"private\": true,\n \"dependencies\": {\n \"dynamic-require\": \"1.0.0\"\n }\n}\n",
"/node_modules/hello_world/hello.js": "import { dynamic } from \"dynamic-require\";\nimport { fileURLToPath } from \"url\";\n\nexport default {\n hello: () => `hello ${dynamic(fileURLToPath(new URL('./world.js', import.meta.url)))}`\n}\n",
"/node_modules/hello_world/README.md": "THis is just a package that consumes another package (`dynamic-require`) which executes a dynamic require.\n",
"/node_modules/dynamic-require/world.js": "module.exports = 'world'\n",
"/node_modules/dynamic-require/package.json": "{\n \"name\": \"dynamic-require\",\n \"version\": \"1.0.0\",\n \"license\": \"ISC\",\n \"private\": true,\n \"main\": \"index.js\"\n\n}\n",
"/node_modules/dynamic-require/index.js": "exports.dynamic = (value) => {\n return require(value)\n}\n"
}
139 changes: 139 additions & 0 deletions packages/endomoat/test/fixture/json/native.json

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions packages/endomoat/test/fixture/json/phony-native.json
@@ -0,0 +1,8 @@
{
"/package.json": "{\n \"name\": \"native\",\n \"version\": \"1.0.0\",\n \"type\": \"module\",\n \"license\": \"ISC\",\n \"private\": true,\n \"main\": \"app.js\",\n \"dependencies\": {\n \"hello\": \"^1.0.0\"\n }\n}\n",
"/index.js": "import addon from 'hello'\nexport const hello = addon.hello()\n",
"/node_modules/hello/package.json": "{\n \"name\": \"hello\",\n \"version\": \"0.0.0\",\n \"description\": \"this code does not run\",\n \"private\": true,\n \"main\": \"index.js\"\n}\n",
"/node_modules/hello/index.js": "var addon = require('./hello')\n\nconsole.log(addon.hello()) // 'world'\n\nmodule.exports = addon\n",
"/node_modules/hello/hello.node": "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000",
"/node_modules/hello/README.md": "This fixture is an example of a package shipping a native module (`hello.node`). `hello.node` is not _actually_ a native module, but it has the right extension and is full of null bytes. Good enough.\n"
}
5 changes: 5 additions & 0 deletions packages/endomoat/test/fixture/native/README.md
@@ -0,0 +1,5 @@
This fixture is not used directly; it's only here in order to create a snapshot:

```bash
npm run start
```
2 changes: 2 additions & 0 deletions packages/endomoat/test/fixture/native/index.js
@@ -0,0 +1,2 @@
import addon from 'hello_world'
export const hello = addon.hello()
Empty file.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file not shown.
Binary file not shown.
Binary file not shown.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 5c30580

Please sign in to comment.