@edge-runtime/vm
Advanced tools
Comparing version 2.1.2 to 2.2.0-beta.0
import type * as EdgePrimitives from '@edge-runtime/primitives'; | ||
import type { VMContext, VMOptions } from './vm'; | ||
import { VM } from './vm'; | ||
export interface EdgeVMOptions<T> { | ||
import type { DispatchFetch } from './types'; | ||
import { VM, type VMContext, type VMOptions } from './vm'; | ||
export interface EdgeVMOptions<T extends EdgeContext> { | ||
/** | ||
@@ -16,2 +16,8 @@ * Provide code generation options to the Node.js VM. | ||
/** | ||
* Code to be evaluated as when the Edge Runtime is created. This is handy | ||
* to run code directly instead of first creating the runtime and then | ||
* evaluating. | ||
*/ | ||
initialCode?: string; | ||
/** | ||
* Provides an initial map to the require cache. | ||
@@ -22,7 +28,4 @@ * If none is given, it will be initialized to an empty map. | ||
} | ||
/** | ||
* An implementation of a VM that pre-loads on its context Edge Primitives. | ||
* The context can be extended from its constructor. | ||
*/ | ||
export declare class EdgeVM<T extends EdgeContext> extends VM<T> { | ||
export declare class EdgeVM<T extends EdgeContext = EdgeContext> extends VM<T> { | ||
readonly dispatchFetch: DispatchFetch; | ||
constructor(options?: EdgeVMOptions<T>); | ||
@@ -38,7 +41,3 @@ } | ||
btoa: typeof EdgePrimitives.btoa; | ||
Cache: typeof EdgePrimitives.Cache; | ||
caches: typeof EdgePrimitives.caches; | ||
CacheStorage: typeof EdgePrimitives.CacheStorage; | ||
console: typeof EdgePrimitives.console; | ||
createCaches: typeof EdgePrimitives.createCaches; | ||
crypto: typeof EdgePrimitives.crypto; | ||
@@ -45,0 +44,0 @@ Crypto: typeof EdgePrimitives.Crypto; |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.EdgeVM = void 0; | ||
const buffer_1 = require("buffer"); | ||
const require_1 = require("./require"); | ||
const vm_1 = require("./vm"); | ||
const vm_2 = require("vm"); | ||
const vm_1 = require("vm"); | ||
const vm_2 = require("./vm"); | ||
const streamsImpl = __importStar(require("@edge-runtime/primitives/streams")); | ||
const urlImpl = __importStar(require("@edge-runtime/primitives/url")); | ||
const cryptoImpl = __importStar(require("@edge-runtime/primitives/crypto")); | ||
const eventsImpl = __importStar(require("@edge-runtime/primitives/events")); | ||
/** | ||
* An implementation of a VM that pre-loads on its context Edge Primitives. | ||
* The context can be extended from its constructor. | ||
* Store handlers that the user defined from code so that we can invoke them | ||
* from the Node.js realm. | ||
*/ | ||
class EdgeVM extends vm_1.VM { | ||
constructor(options = {}) { | ||
let unhandledRejectionHandlers; | ||
let uncaughtExceptionHandlers; | ||
class EdgeVM extends vm_2.VM { | ||
constructor(options) { | ||
super({ | ||
...options, | ||
extend: (context) => { | ||
return options.extend | ||
return (options === null || options === void 0 ? void 0 : options.extend) | ||
? options.extend(addPrimitives(context)) | ||
@@ -22,5 +50,198 @@ : addPrimitives(context); | ||
}); | ||
Object.defineProperty(this.context, '__onUnhandledRejectionHandlers', { | ||
set: registerUnhandledRejectionHandlers, | ||
configurable: false, | ||
enumerable: false, | ||
}); | ||
Object.defineProperty(this, '__rejectionHandlers', { | ||
get: () => unhandledRejectionHandlers, | ||
configurable: false, | ||
enumerable: false, | ||
}); | ||
Object.defineProperty(this.context, '__onErrorHandlers', { | ||
set: registerUncaughtExceptionHandlers, | ||
configurable: false, | ||
enumerable: false, | ||
}); | ||
Object.defineProperty(this, '__errorHandlers', { | ||
get: () => uncaughtExceptionHandlers, | ||
configurable: false, | ||
enumerable: false, | ||
}); | ||
this.evaluate(getDefineEventListenersCode()); | ||
this.dispatchFetch = this.evaluate(getDispatchFetchCode()); | ||
for (const item of constructorsToPatchInstanceOf) { | ||
patchInstanceOf(item, this.context); | ||
} | ||
if (options === null || options === void 0 ? void 0 : options.initialCode) { | ||
this.evaluate(options.initialCode); | ||
} | ||
} | ||
} | ||
exports.EdgeVM = EdgeVM; | ||
/** | ||
* A list of constructors that need to be patched to make sure that the | ||
* `instanceof` operator works as expected from within the vm context, | ||
* even when passing it objects that were created in the Node.js realm. | ||
* | ||
* Example: the return value from `new TextEncoder().encode("hello")` is a | ||
* Uint8Array. If `TextEncoder` is coming from the Node.js realm, then the | ||
* following will be false, which doesn't fit the expectation of the user: | ||
* ```ts | ||
* new TextEncoder().encode("hello") instanceof Uint8Array | ||
* ``` | ||
* | ||
* This is because the `Uint8Array` in the `vm` context is not the same | ||
* as the one in the Node.js realm. | ||
* | ||
* Patching the constructors in the `vm` is done by the {@link patchInstanceOf} | ||
* function, and this is the list of constructors that need to be patched. | ||
*/ | ||
const constructorsToPatchInstanceOf = [ | ||
'Object', | ||
'Array', | ||
'RegExp', | ||
'Uint8Array', | ||
'ArrayBuffer', | ||
'Error', | ||
'SyntaxError', | ||
'TypeError', | ||
]; | ||
function patchInstanceOf(item, ctx) { | ||
// @ts-ignore | ||
ctx[Symbol.for(`node:${item}`)] = eval(item); | ||
return (0, vm_1.runInContext)(` | ||
globalThis.${item} = new Proxy(${item}, { | ||
get(target, prop, receiver) { | ||
if (prop === Symbol.hasInstance && receiver === globalThis.${item}) { | ||
const nodeTarget = globalThis[Symbol.for('node:${item}')]; | ||
if (nodeTarget) { | ||
return function(instance) { | ||
return instance instanceof target || instance instanceof nodeTarget; | ||
}; | ||
} else { | ||
throw new Error('node target must exist') | ||
} | ||
} | ||
return Reflect.get(target, prop, receiver); | ||
} | ||
}) | ||
`, ctx); | ||
} | ||
/** | ||
* Register system-level handlers to make sure that we report to the user | ||
* whenever there is an unhandled rejection or exception before the process crashes. | ||
* Do it on demand so we don't swallow rejections/errors for no reason. | ||
*/ | ||
function registerUnhandledRejectionHandlers(handlers) { | ||
if (!unhandledRejectionHandlers) { | ||
process.on('unhandledRejection', function invokeRejectionHandlers(reason, promise) { | ||
unhandledRejectionHandlers.forEach((handler) => handler({ reason, promise })); | ||
}); | ||
} | ||
unhandledRejectionHandlers = handlers; | ||
} | ||
function registerUncaughtExceptionHandlers(handlers) { | ||
if (!uncaughtExceptionHandlers) { | ||
process.on('uncaughtException', function invokeErrorHandlers(error) { | ||
uncaughtExceptionHandlers.forEach((handler) => handler(error)); | ||
}); | ||
} | ||
uncaughtExceptionHandlers = handlers; | ||
} | ||
/** | ||
* Generates polyfills for addEventListener and removeEventListener. It keeps | ||
* all listeners in hidden property __listeners. It will also call a hook | ||
* `__onUnhandledRejectionHandler` and `__onErrorHandler` when unhandled rejection | ||
* events are added or removed and prevent from having more than one FetchEvent | ||
* handler. | ||
*/ | ||
function getDefineEventListenersCode() { | ||
return ` | ||
Object.defineProperty(self, '__listeners', { | ||
configurable: false, | ||
enumerable: false, | ||
value: {}, | ||
writable: true, | ||
}) | ||
function __conditionallyUpdatesHandlerList(eventType) { | ||
if (eventType === 'unhandledrejection') { | ||
self.__onUnhandledRejectionHandlers = self.__listeners[eventType]; | ||
} else if (eventType === 'error') { | ||
self.__onErrorHandlers = self.__listeners[eventType]; | ||
} | ||
} | ||
function addEventListener(type, handler) { | ||
const eventType = type.toLowerCase(); | ||
if (eventType === 'fetch' && self.__listeners.fetch) { | ||
throw new TypeError('You can register just one "fetch" event listener'); | ||
} | ||
self.__listeners[eventType] = self.__listeners[eventType] || []; | ||
self.__listeners[eventType].push(handler); | ||
__conditionallyUpdatesHandlerList(eventType); | ||
} | ||
function removeEventListener(type, handler) { | ||
const eventType = type.toLowerCase(); | ||
if (self.__listeners[eventType]) { | ||
self.__listeners[eventType] = self.__listeners[eventType].filter(item => { | ||
return item !== handler; | ||
}); | ||
if (self.__listeners[eventType].length === 0) { | ||
delete self.__listeners[eventType]; | ||
} | ||
} | ||
__conditionallyUpdatesHandlerList(eventType); | ||
} | ||
`; | ||
} | ||
/** | ||
* Generates the code to dispatch a FetchEvent invoking the handlers defined | ||
* for such events. In case there is no event handler defined it will throw | ||
* an error. | ||
*/ | ||
function getDispatchFetchCode() { | ||
return `(async function dispatchFetch(input, init) { | ||
const request = new Request(input, init); | ||
const event = new FetchEvent(request); | ||
if (!self.__listeners.fetch) { | ||
throw new Error("No fetch event listeners found"); | ||
} | ||
const getResponse = ({ response, error }) => { | ||
if (error || !response || !(response instanceof Response)) { | ||
console.error(error ? error.toString() : 'The event listener did not respond') | ||
response = new Response(null, { | ||
statusText: 'Internal Server Error', | ||
status: 500 | ||
}) | ||
} | ||
response.waitUntil = () => Promise.all(event.awaiting); | ||
if (response.status < 300 || response.status >= 400 ) { | ||
response.headers.delete('content-encoding'); | ||
response.headers.delete('transform-encoding'); | ||
response.headers.delete('content-length'); | ||
} | ||
return response; | ||
} | ||
try { | ||
await self.__listeners.fetch[0].call(event, event) | ||
} catch (error) { | ||
return getResponse({ error }) | ||
} | ||
return Promise.resolve(event.response) | ||
.then(response => getResponse({ response })) | ||
.catch(error => getResponse({ error })) | ||
})`; | ||
} | ||
function addPrimitives(context) { | ||
@@ -38,25 +259,32 @@ defineProperty(context, 'self', { enumerable: true, value: context }); | ||
exports: (0, require_1.requireWithCache)({ | ||
path: require.resolve('@edge-runtime/primitives/console'), | ||
context, | ||
path: require.resolve('@edge-runtime/primitives/console'), | ||
scopedContext: { console }, | ||
}), | ||
nonenumerable: ['console'], | ||
}); | ||
const encodings = (0, require_1.requireWithCache)({ | ||
context, | ||
path: require.resolve('@edge-runtime/primitives/encoding'), | ||
scopedContext: { Buffer: buffer_1.Buffer, global: {} }, | ||
const atob = (str) => Buffer.from(str, 'base64').toString('binary'); | ||
const btoa = (str) => Buffer.from(str, 'binary').toString('base64'); | ||
// Events | ||
defineProperties(context, { | ||
exports: eventsImpl, | ||
nonenumerable: [ | ||
'Event', | ||
'EventTarget', | ||
'FetchEvent', | ||
'PromiseRejectionEvent', | ||
], | ||
}); | ||
// Encoding APIs | ||
defineProperties(context, { | ||
exports: encodings, | ||
exports: { atob, btoa, TextEncoder, TextDecoder }, | ||
nonenumerable: ['atob', 'btoa', 'TextEncoder', 'TextDecoder'], | ||
}); | ||
const streams = (0, require_1.requireWithCache)({ | ||
path: require.resolve('@edge-runtime/primitives/streams'), | ||
const textEncodingStreamImpl = (0, require_1.requireWithFakeGlobalScope)({ | ||
context, | ||
path: require.resolve('@edge-runtime/primitives/text-encoding-streams'), | ||
scopedContext: streamsImpl, | ||
}); | ||
// Streams | ||
defineProperties(context, { | ||
exports: streams, | ||
exports: { ...streamsImpl, ...textEncodingStreamImpl }, | ||
nonenumerable: [ | ||
@@ -73,9 +301,10 @@ 'ReadableStream', | ||
}); | ||
const abort = (0, require_1.requireWithCache)({ | ||
// AbortController | ||
const abortControllerImpl = (0, require_1.requireWithFakeGlobalScope)({ | ||
path: require.resolve('@edge-runtime/primitives/abort-controller'), | ||
context, | ||
path: require.resolve('@edge-runtime/primitives/abort-controller'), | ||
scopedContext: eventsImpl, | ||
}); | ||
// AbortController | ||
defineProperties(context, { | ||
exports: abort, | ||
exports: abortControllerImpl, | ||
nonenumerable: ['AbortController', 'AbortSignal', 'DOMException'], | ||
@@ -85,56 +314,42 @@ }); | ||
defineProperties(context, { | ||
exports: (0, require_1.requireWithCache)({ | ||
cache: new Map([['punycode', { exports: require('punycode') }]]), | ||
context, | ||
path: require.resolve('@edge-runtime/primitives/url'), | ||
scopedContext: { | ||
TextEncoder: encodings.TextEncoder, | ||
TextDecoder: encodings.TextDecoder, | ||
}, | ||
}), | ||
exports: urlImpl, | ||
nonenumerable: ['URL', 'URLSearchParams', 'URLPattern'], | ||
}); | ||
const blob = (0, require_1.requireWithCache)({ | ||
context, | ||
path: require.resolve('@edge-runtime/primitives/blob'), | ||
}); | ||
// Blob | ||
defineProperties(context, { | ||
exports: blob, | ||
exports: (0, require_1.requireWithFakeGlobalScope)({ | ||
context, | ||
path: require.resolve('@edge-runtime/primitives/blob'), | ||
scopedContext: streamsImpl, | ||
}), | ||
nonenumerable: ['Blob'], | ||
}); | ||
const webFetch = (0, require_1.requireWithCache)({ | ||
context, | ||
cache: new Map([ | ||
['abort-controller', { exports: abort }], | ||
['assert', { exports: require('assert') }], | ||
['buffer', { exports: require('buffer') }], | ||
['events', { exports: require('events') }], | ||
['http', { exports: require('http') }], | ||
['net', { exports: require('net') }], | ||
['perf_hooks', { exports: require('perf_hooks') }], | ||
['querystring', { exports: require('querystring') }], | ||
['stream', { exports: require('stream') }], | ||
['tls', { exports: require('tls') }], | ||
['util', { exports: require('util') }], | ||
['zlib', { exports: require('zlib') }], | ||
[ | ||
require.resolve('@edge-runtime/primitives/streams'), | ||
{ exports: streams }, | ||
], | ||
[require.resolve('@edge-runtime/primitives/blob'), { exports: blob }], | ||
]), | ||
path: require.resolve('@edge-runtime/primitives/fetch'), | ||
scopedContext: { | ||
Uint8Array: createUint8ArrayForContext(context), | ||
Buffer: buffer_1.Buffer, | ||
global: {}, | ||
queueMicrotask, | ||
setImmediate, | ||
clearImmediate, | ||
}, | ||
// Structured Clone | ||
defineProperties(context, { | ||
exports: (0, require_1.requireWithFakeGlobalScope)({ | ||
path: require.resolve('@edge-runtime/primitives/structured-clone'), | ||
context, | ||
scopedContext: streamsImpl, | ||
}), | ||
nonenumerable: ['structuredClone'], | ||
}); | ||
// Fetch APIs | ||
defineProperties(context, { | ||
exports: webFetch, | ||
exports: (0, require_1.requireWithFakeGlobalScope)({ | ||
context, | ||
cache: new Map([ | ||
['abort-controller', { exports: abortControllerImpl }], | ||
['streams', { exports: streamsImpl }], | ||
]), | ||
path: require.resolve('@edge-runtime/primitives/fetch'), | ||
scopedContext: { | ||
...streamsImpl, | ||
...urlImpl, | ||
structuredClone: context.structuredClone, | ||
...eventsImpl, | ||
AbortController: context.AbortController, | ||
DOMException: context.DOMException, | ||
AbortSignal: context.AbortSignal, | ||
}, | ||
}), | ||
nonenumerable: [ | ||
@@ -147,58 +362,11 @@ 'fetch', | ||
'Response', | ||
'WebSocket', | ||
], | ||
}); | ||
// Cache | ||
defineProperties(context, { | ||
exports: (0, require_1.requireWithCache)({ | ||
cache: new Map([ | ||
[ | ||
require.resolve('@edge-runtime/primitives/fetch'), | ||
{ exports: webFetch }, | ||
], | ||
]), | ||
context, | ||
path: require.resolve('@edge-runtime/primitives/cache'), | ||
scopedContext: { global: {} }, | ||
}), | ||
enumerable: ['caches'], | ||
nonenumerable: ['Cache', 'CacheStorage'], | ||
}); | ||
// Crypto | ||
defineProperties(context, { | ||
exports: (0, require_1.requireWithCache)({ | ||
context, | ||
cache: new Map([ | ||
['crypto', { exports: require('crypto') }], | ||
['process', { exports: require('process') }], | ||
]), | ||
path: require.resolve('@edge-runtime/primitives/crypto'), | ||
scopedContext: { | ||
Buffer: buffer_1.Buffer, | ||
Uint8Array: createUint8ArrayForContext(context), | ||
}, | ||
}), | ||
exports: cryptoImpl, | ||
enumerable: ['crypto'], | ||
nonenumerable: ['Crypto', 'CryptoKey', 'SubtleCrypto'], | ||
}); | ||
// Events | ||
defineProperties(context, { | ||
exports: (0, require_1.requireWithCache)({ | ||
context, | ||
path: require.resolve('@edge-runtime/primitives/events'), | ||
}), | ||
nonenumerable: [ | ||
'Event', | ||
'EventTarget', | ||
'FetchEvent', | ||
'PromiseRejectionEvent', | ||
], | ||
}); | ||
// Structured Clone | ||
defineProperties(context, { | ||
exports: (0, require_1.requireWithCache)({ | ||
context, | ||
path: require.resolve('@edge-runtime/primitives/structured-clone'), | ||
}), | ||
nonenumerable: ['structuredClone'], | ||
}); | ||
return context; | ||
@@ -235,19 +403,2 @@ } | ||
} | ||
function createUint8ArrayForContext(context) { | ||
return new Proxy((0, vm_2.runInContext)('Uint8Array', context), { | ||
// on every construction (new Uint8Array(...)) | ||
construct(target, args) { | ||
// construct it | ||
const value = new target(...args); | ||
// if this is not a buffer | ||
if (!(args[0] instanceof buffer_1.Buffer)) { | ||
// return what we just constructed | ||
return value; | ||
} | ||
// if it is a buffer, then we spread the binary data into an array, | ||
// and build the Uint8Array from that | ||
return new target([...value]); | ||
}, | ||
}); | ||
} | ||
//# sourceMappingURL=edge-vm.js.map |
/// <reference types="node" /> | ||
import type { Dictionary } from './types'; | ||
import type { Context } from 'vm'; | ||
@@ -11,3 +10,3 @@ /** | ||
context: Context; | ||
requireCache: Map<string, Dictionary>; | ||
requireCache: Map<string, Record<string | number, any>>; | ||
dependencies: Array<{ | ||
@@ -28,1 +27,8 @@ mapExports: { | ||
}): any; | ||
export declare function requireWithFakeGlobalScope(params: { | ||
context: Context; | ||
cache?: Map<string, any>; | ||
path: string; | ||
references?: Set<string>; | ||
scopedContext: Record<string, any>; | ||
}): {}; |
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.requireWithCache = exports.createRequire = exports.requireDependencies = void 0; | ||
exports.requireWithFakeGlobalScope = exports.requireWithCache = exports.createRequire = exports.requireDependencies = void 0; | ||
const fs_1 = require("fs"); | ||
const vm_1 = require("vm"); | ||
const path_1 = require("path"); | ||
const module_1 = __importDefault(require("module")); | ||
/** | ||
@@ -57,2 +61,27 @@ * Allows to require a series of dependencies provided by their path | ||
exports.requireWithCache = requireWithCache; | ||
function requireWithFakeGlobalScope(params) { | ||
const resolved = require.resolve(params.path); | ||
const getModuleCode = `(function(module,exports,require,__dirname,__filename,globalThis,${Object.keys(params.scopedContext).join(',')}) {${(0, fs_1.readFileSync)(resolved, 'utf-8')}\n})`; | ||
const module = { | ||
exports: {}, | ||
loaded: false, | ||
id: resolved, | ||
}; | ||
const moduleRequire = (module_1.default.createRequire || module_1.default.createRequireFromPath)(resolved); | ||
function throwingRequire(path) { | ||
var _a; | ||
if (path.startsWith('./')) { | ||
const moduleName = path.replace(/^\.\//, ''); | ||
if (!((_a = params.cache) === null || _a === void 0 ? void 0 : _a.has(moduleName))) { | ||
throw new Error(`Cannot find module '${moduleName}'`); | ||
} | ||
return params.cache.get(moduleName).exports; | ||
} | ||
return moduleRequire(path); | ||
} | ||
throwingRequire.resolve = moduleRequire.resolve.bind(moduleRequire); | ||
eval(getModuleCode)(module, module.exports, throwingRequire, (0, path_1.dirname)(resolved), resolved, params.context, ...Object.values(params.scopedContext)); | ||
return module.exports; | ||
} | ||
exports.requireWithFakeGlobalScope = requireWithFakeGlobalScope; | ||
//# sourceMappingURL=require.js.map |
@@ -1,7 +0,11 @@ | ||
/** | ||
* Just any type of object indexed by string or numbers where the value can | ||
* be anything or the provided generic. | ||
*/ | ||
export interface Dictionary<T = any> { | ||
[key: string | number]: T; | ||
export interface DispatchFetch { | ||
(input: string, init?: RequestInit): Promise<Response & { | ||
waitUntil: () => Promise<any>; | ||
}>; | ||
} | ||
export interface RejectionHandler { | ||
(reason?: {} | null, promise?: Promise<any>): void; | ||
} | ||
export interface ErrorHandler { | ||
(error?: {} | null): void; | ||
} |
/// <reference types="node" /> | ||
import type { CreateContextOptions } from 'vm'; | ||
import type { Dictionary } from './types'; | ||
export interface VMOptions<T> { | ||
@@ -19,3 +18,3 @@ /** | ||
*/ | ||
requireCache?: Map<string, Dictionary>; | ||
requireCache?: Map<string, Record<string | number, any>>; | ||
} | ||
@@ -27,5 +26,5 @@ /** | ||
*/ | ||
export declare class VM<T extends Dictionary> { | ||
export declare class VM<T extends Record<string | number, any>> { | ||
private readonly requireFn; | ||
readonly requireCache: Map<string, Dictionary>; | ||
readonly requireCache: Map<string, Record<string | number, any>>; | ||
readonly context: VMContext & T; | ||
@@ -41,3 +40,3 @@ constructor(options?: VMOptions<T>); | ||
*/ | ||
require<T extends Dictionary = any>(filepath: string): T; | ||
require<T extends Record<string | number, any> = any>(filepath: string): T; | ||
/** | ||
@@ -48,3 +47,3 @@ * Same as `require` but it will copy each of the exports in the context | ||
*/ | ||
requireInContext<T extends Dictionary = any>(filepath: string): void; | ||
requireInContext<T extends Record<string | number, any> = any>(filepath: string): void; | ||
/** | ||
@@ -51,0 +50,0 @@ * Same as `requireInContext` but allows to pass the code instead of a |
@@ -5,3 +5,3 @@ { | ||
"homepage": "https://edge-runtime.vercel.app/packages/vm", | ||
"version": "2.1.2", | ||
"version": "2.2.0-beta.0", | ||
"main": "dist/index.js", | ||
@@ -26,5 +26,2 @@ "repository": { | ||
], | ||
"dependencies": { | ||
"@edge-runtime/primitives": "2.1.2" | ||
}, | ||
"engines": { | ||
@@ -41,2 +38,13 @@ "node": ">=14" | ||
"types": "dist/index.d.ts", | ||
"dependencies": { | ||
"@edge-runtime/primitives": "2.2.0-beta.0" | ||
}, | ||
"devDependencies": { | ||
"@types/multer": "1.4.7", | ||
"@types/test-listen": "1.1.0", | ||
"@types/ws": "8.5.3", | ||
"multer": "1.4.5-lts.1", | ||
"test-listen": "1.1.0", | ||
"ws": "8.13.0" | ||
}, | ||
"scripts": { | ||
@@ -43,0 +51,0 @@ "build": "tsc --project ./tsconfig.prod.json", |
<div align="center"> | ||
<br> | ||
<img src="https://edge-runtime.vercel.app/og-image.png" alt="edge-runtime logo"> | ||
<img src="https://user-images.githubusercontent.com/2096101/235130063-e561514e-1f66-4ff6-9034-70dbf7ca3260.png#gh-dark-mode-only"> | ||
<img src="https://user-images.githubusercontent.com/2096101/235127419-ac6fe609-d0cd-4339-a593-c48305a83823.png#gh-light-mode-only"> | ||
<br> | ||
@@ -5,0 +6,0 @@ <br> |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses eval() which is a dangerous function. This prevents the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 3 instances in 1 package
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
86574
796
38
2
6
1
8
+ Added@edge-runtime/primitives@2.2.0-beta.0(transitive)
- Removed@edge-runtime/primitives@2.1.2(transitive)