VM (JavaScript ausführen)
[Stabil: 2 - Stabil]
Stabil: 2 Stabilität: 2 - Stabil
Quellcode: lib/vm.js
Das Modul node:vm
ermöglicht das Kompilieren und Ausführen von Code innerhalb von V8 Virtual Machine-Kontexten.
Das Modul node:vm
ist kein Sicherheitsmechanismus. Verwenden Sie es nicht, um nicht vertrauenswürdigen Code auszuführen.
JavaScript-Code kann kompiliert und sofort ausgeführt oder kompiliert, gespeichert und später ausgeführt werden.
Ein häufiger Anwendungsfall ist das Ausführen des Codes in einem anderen V8-Kontext. Dies bedeutet, dass der aufgerufene Code ein anderes globales Objekt hat als der aufrufende Code.
Man kann den Kontext bereitstellen, indem man ein Objekt kontextualisiert. Der aufgerufene Code behandelt jede Eigenschaft im Kontext wie eine globale Variable. Jegliche Änderungen an globalen Variablen, die durch den aufgerufenen Code verursacht werden, spiegeln sich im Kontextobjekt wider.
const vm = require('node:vm');
const x = 1;
const context = { x: 2 };
vm.createContext(context); // Kontextualisiere das Objekt.
const code = 'x += 40; var y = 17;';
// `x` und `y` sind globale Variablen im Kontext.
// Ursprünglich hat x den Wert 2, da dies der Wert von context.x ist.
vm.runInContext(code, context);
console.log(context.x); // 42
console.log(context.y); // 17
console.log(x); // 1; y ist nicht definiert.
Klasse: vm.Script
Hinzugefügt in: v0.3.1
Instanzen der Klasse vm.Script
enthalten vorkompilierte Skripte, die in bestimmten Kontexten ausgeführt werden können.
new vm.Script(code[, options])
[Historie]
Version | Änderungen |
---|---|
v21.7.0, v20.12.0 | Unterstützung für vm.constants.USE_MAIN_CONTEXT_DEFAULT_LOADER hinzugefügt. |
v17.0.0, v16.12.0 | Unterstützung für Importattribute für den Parameter importModuleDynamically hinzugefügt. |
v10.6.0 | produceCachedData ist zugunsten von script.createCachedData() veraltet. |
v5.7.0 | Die Optionen cachedData und produceCachedData werden jetzt unterstützt. |
v0.3.1 | Hinzugefügt in: v0.3.1 |
code
<string> Der zu kompilierende JavaScript-Code.options
<Object> | <string>filename
<string> Gibt den Dateinamen an, der in Stacktraces verwendet wird, die von diesem Skript erzeugt werden. Standard:'evalmachine.\<anonymous\>'
.lineOffset
<number> Gibt den Zeilennummernoffset an, der in Stacktraces angezeigt wird, die von diesem Skript erzeugt werden. Standard:0
.columnOffset
<number> Gibt den Spaltennummernoffset der ersten Zeile an, der in Stacktraces angezeigt wird, die von diesem Skript erzeugt werden. Standard:0
.cachedData
<Buffer> | <TypedArray> | <DataView> Stellt einen optionalenBuffer
oderTypedArray
oderDataView
mit den Code-Cache-Daten von V8 für die bereitgestellte Quelle bereit. Wenn angegeben, wird der WertcachedDataRejected
entweder auftrue
oderfalse
gesetzt, je nachdem, ob die Daten von V8 akzeptiert werden.produceCachedData
<boolean> Wenntrue
und keinecachedData
vorhanden sind, versucht V8, Code-Cache-Daten fürcode
zu erzeugen. Bei Erfolg wird einBuffer
mit den Code-Cache-Daten von V8 erzeugt und in der EigenschaftcachedData
der zurückgegebenenvm.Script
-Instanz gespeichert. Der WertcachedDataProduced
wird entweder auftrue
oderfalse
gesetzt, je nachdem, ob die Code-Cache-Daten erfolgreich erzeugt wurden. Diese Option ist zugunsten vonscript.createCachedData()
veraltet. Standard:false
.importModuleDynamically
<Function> | <vm.constants.USE_MAIN_CONTEXT_DEFAULT_LOADER> Wird verwendet, um anzugeben, wie die Module während der Auswertung dieses Skripts geladen werden sollen, wennimport()
aufgerufen wird. Diese Option ist Teil der experimentellen Module-API. Wir empfehlen nicht, sie in einer Produktionsumgebung zu verwenden. Ausführliche Informationen finden Sie unter Unterstützung von dynamischemimport()
in Kompilierungs-APIs.
Wenn options
ein String ist, dann gibt er den Dateinamen an.
Das Erstellen eines neuen vm.Script
-Objekts kompiliert code
, führt ihn aber nicht aus. Das kompilierte vm.Script
kann später mehrmals ausgeführt werden. Der code
ist nicht an ein globales Objekt gebunden; stattdessen wird er vor jeder Ausführung nur für diese Ausführung gebunden.
script.cachedDataRejected
Hinzugefügt in: v5.7.0
Wenn cachedData
bereitgestellt wird, um das vm.Script
zu erstellen, wird dieser Wert entweder auf true
oder false
gesetzt, je nachdem, ob die Daten von V8 akzeptiert werden. Andernfalls ist der Wert undefined
.
script.createCachedData()
Hinzugefügt in: v10.6.0
- Gibt zurück: <Buffer>
Erstellt einen Code-Cache, der mit der cachedData
-Option des Script
-Konstruktors verwendet werden kann. Gibt einen Buffer
zurück. Diese Methode kann jederzeit und beliebig oft aufgerufen werden.
Der Code-Cache des Script
enthält keine JavaScript-beobachtbaren Zustände. Der Code-Cache kann sicher zusammen mit dem Skript-Sourcecode gespeichert und verwendet werden, um mehrmals neue Script
-Instanzen zu erstellen.
Funktionen im Script
-Sourcecode können als verzögert kompilierte Funktionen markiert werden, die nicht bei der Erstellung des Script
kompiliert werden. Diese Funktionen werden kompiliert, wenn sie das erste Mal aufgerufen werden. Der Code-Cache serialisiert die Metadaten, die V8 aktuell über das Script
hat, und kann diese verwenden, um zukünftige Kompilierungen zu beschleunigen.
const script = new vm.Script(`
function add(a, b) {
return a + b;
}
const x = add(1, 2);
`);
const cacheWithoutAdd = script.createCachedData();
// In `cacheWithoutAdd` wird die Funktion `add()` für die vollständige Kompilierung
// beim Aufruf markiert.
script.runInThisContext();
const cacheWithAdd = script.createCachedData();
// `cacheWithAdd` enthält die vollständig kompilierte Funktion `add()`.
script.runInContext(contextifiedObject[, options])
[Verlauf]
Version | Änderungen |
---|---|
v6.3.0 | Die Option breakOnSigint wird jetzt unterstützt. |
v0.3.1 | Hinzugefügt in: v0.3.1 |
contextifiedObject
<Object> Ein kontextualisiertes Objekt, wie von der Methodevm.createContext()
zurückgegeben.options
<Object>displayErrors
<boolean> Wenntrue
, wird bei einemError
während der Kompilierung descode
die Codezeile, die den Fehler verursacht, an den Stack Trace angehängt. Standard:true
.timeout
<integer> Gibt die Anzahl der Millisekunden an, diecode
ausgeführt werden soll, bevor die Ausführung beendet wird. Wenn die Ausführung beendet wird, wird einError
ausgelöst. Dieser Wert muss eine strikt positive ganze Zahl sein.breakOnSigint
<boolean> Wenntrue
beendet der Empfang vonSIGINT
(+) die Ausführung und löst einenError
aus. Vorhandene Handler für das Ereignis, die überprocess.on('SIGINT')
angehängt wurden, werden während der Skriptausführung deaktiviert, funktionieren danach aber wieder. Standard:false
.
Gibt zurück: <any> Das Ergebnis der allerletzten im Skript ausgeführten Anweisung.
Führt den von dem vm.Script
-Objekt enthaltenen kompilierten Code innerhalb des gegebenen contextifiedObject
aus und gibt das Ergebnis zurück. Der laufende Code hat keinen Zugriff auf den lokalen Gültigkeitsbereich.
Das folgende Beispiel kompiliert Code, der eine globale Variable inkrementiert, den Wert einer anderen globalen Variable setzt und dann den Code mehrmals ausführt. Die globalen Variablen sind im context
-Objekt enthalten.
const vm = require('node:vm');
const context = {
animal: 'cat',
count: 2,
};
const script = new vm.Script('count += 1; name = "kitty";');
vm.createContext(context);
for (let i = 0; i < 10; ++i) {
script.runInContext(context);
}
console.log(context);
// Gibt aus: { animal: 'cat', count: 12, name: 'kitty' }
Die Verwendung der Optionen timeout
oder breakOnSigint
führt zum Starten neuer Event Loops und entsprechender Threads, was einen nicht zu vernachlässigenden Performance-Overhead verursacht.
script.runInNewContext([contextObject[, options]])
[Verlauf]
Version | Änderungen |
---|---|
v22.8.0, v20.18.0 | Das Argument contextObject akzeptiert nun vm.constants.DONT_CONTEXTIFY . |
v14.6.0 | Die Option microtaskMode wird jetzt unterstützt. |
v10.0.0 | Die Option contextCodeGeneration wird jetzt unterstützt. |
v6.3.0 | Die Option breakOnSigint wird jetzt unterstützt. |
v0.3.1 | Hinzugefügt in: v0.3.1 |
contextObject
<Object> | <vm.constants.DONT_CONTEXTIFY> | <undefined> Entwedervm.constants.DONT_CONTEXTIFY
oder ein Objekt, das kontextualisiert wird. Wennundefined
, wird ein leeres, kontextualisiertes Objekt zur Abwärtskompatibilität erstellt.options
<Object>displayErrors
<boolean> Wenntrue
, wird bei Auftreten einesError
beim Kompilieren descode
die Codezeile, die den Fehler verursacht, an den Stack-Trace angehängt. Standard:true
.timeout
<integer> Gibt die Anzahl der Millisekunden an, diecode
vor dem Beenden der Ausführung ausgeführt werden soll. Wenn die Ausführung beendet wird, wird einError
ausgelöst. Dieser Wert muss eine strikt positive ganze Zahl sein.breakOnSigint
<boolean> Wenntrue
, beendet der Empfang vonSIGINT
(+) die Ausführung und löst einenError
aus. Vorhandene Handler für das Ereignis, die überprocess.on('SIGINT')
angehängt wurden, werden während der Skriptausführung deaktiviert, funktionieren aber danach weiterhin. Standard:false
.contextName
<string> Für Menschen lesbarer Name des neu erstellten Kontexts. Standard:'VM Context i'
, wobeii
ein aufsteigender numerischer Index des erstellten Kontexts ist.contextOrigin
<string> Ursprung entsprechend dem neu erstellten Kontext zu Anzeigezwecken. Der Ursprung sollte wie eine URL formatiert sein, aber nur mit dem Schema, dem Host und dem Port (falls erforderlich), wie der Wert der Eigenschafturl.origin
einesURL
-Objekts. Insbesondere sollte diese Zeichenfolge den nachgestellten Schrägstrich weglassen, da dieser einen Pfad kennzeichnet. Standard:''
.contextCodeGeneration
<Object>strings
<boolean> Wenn auf false gesetzt, lösen alle Aufrufe voneval
oder Funktionskonstruktoren (Function
,GeneratorFunction
usw.) einenEvalError
aus. Standard:true
.wasm
<boolean> Wenn auf false gesetzt, löst jeder Versuch, ein WebAssembly-Modul zu kompilieren, einenWebAssembly.CompileError
aus. Standard:true
.microtaskMode
<string> Wenn aufafterEvaluate
gesetzt, werden Mikrotasks (Tasks, die durchPromise
s undasync function
s geplant wurden) unmittelbar nach der Ausführung des Skripts ausgeführt. Sie sind in diesem Fall in dentimeout
- undbreakOnSigint
-Bereichen enthalten.
Gibt zurück: <any> das Ergebnis der allerletzten im Skript ausgeführten Anweisung.
Diese Methode ist eine Abkürzung für script.runInContext(vm.createContext(options), options)
. Sie erledigt mehrere Dinge gleichzeitig:
Das folgende Beispiel kompiliert Code, der eine globale Variable setzt, und führt den Code dann mehrmals in verschiedenen Kontexten aus. Die globalen Variablen werden in jedem einzelnen context
gesetzt und darin enthalten.
const vm = require('node:vm');
const script = new vm.Script('globalVar = "set"');
const contexts = [{}, {}, {}];
contexts.forEach((context) => {
script.runInNewContext(context);
});
console.log(contexts);
// Gibt aus: [{ globalVar: 'set' }, { globalVar: 'set' }, { globalVar: 'set' }]
// Dies würde einen Fehler auslösen, wenn der Kontext aus einem kontextualisierten Objekt erstellt würde.
// vm.constants.DONT_CONTEXTIFY ermöglicht das Erstellen von Kontexten mit normalen
// globalen Objekten, die eingefroren werden können.
const freezeScript = new vm.Script('Object.freeze(globalThis); globalThis;');
const frozenContext = freezeScript.runInNewContext(vm.constants.DONT_CONTEXTIFY);
script.runInThisContext([options])
[Historie]
Version | Änderungen |
---|---|
v6.3.0 | Die Option breakOnSigint wird jetzt unterstützt. |
v0.3.1 | Hinzugefügt in: v0.3.1 |
options
<Object>displayErrors
<boolean> Wenntrue
, wird, falls einError
während der Kompilierung descode
auftritt, die Codezeile, die den Fehler verursacht, an den Stack-Trace angehängt. Standard:true
.timeout
<integer> Gibt die Anzahl der Millisekunden an, diecode
ausgeführt werden soll, bevor die Ausführung beendet wird. Wenn die Ausführung beendet wird, wird einError
ausgelöst. Dieser Wert muss eine strikt positive ganze Zahl sein.breakOnSigint
<boolean> Wenntrue
, beendet der Empfang vonSIGINT
(+) die Ausführung und wirft einenError
. Bestehende Handler für das Ereignis, die überprocess.on('SIGINT')
angehängt wurden, werden während der Skriptausführung deaktiviert, funktionieren aber danach weiterhin. Standard:false
.
Gibt zurück: <any> das Ergebnis der allerletzten Anweisung, die im Skript ausgeführt wurde.
Führt den kompilierten Code, der von vm.Script
enthalten ist, im Kontext des aktuellen global
-Objekts aus. Der ausgeführte Code hat keinen Zugriff auf den lokalen Scope, hat aber Zugriff auf das aktuelle global
-Objekt.
Das folgende Beispiel kompiliert Code, der eine global
-Variable inkrementiert, und führt diesen Code dann mehrmals aus:
const vm = require('node:vm');
global.globalVar = 0;
const script = new vm.Script('globalVar += 1', { filename: 'myfile.vm' });
for (let i = 0; i < 1000; ++i) {
script.runInThisContext();
}
console.log(globalVar);
// 1000
script.sourceMapURL
Hinzugefügt in: v19.1.0, v18.13.0
Wenn das Skript aus einer Quelle kompiliert wird, die einen Source-Map-Magic-Kommentar enthält, wird diese Eigenschaft auf die URL der Source Map gesetzt.
import vm from 'node:vm';
const script = new vm.Script(`
function myFunc() {}
//# sourceMappingURL=sourcemap.json
`);
console.log(script.sourceMapURL);
// Prints: sourcemap.json
const vm = require('node:vm');
const script = new vm.Script(`
function myFunc() {}
//# sourceMappingURL=sourcemap.json
`);
console.log(script.sourceMapURL);
// Prints: sourcemap.json
Klasse: vm.Module
Hinzugefügt in: v13.0.0, v12.16.0
[Stabil: 1 - Experimentell]
Stabil: 1 Stabilität: 1 - Experimentell
Diese Funktion ist nur mit dem aktivierten Befehlsflag --experimental-vm-modules
verfügbar.
Die Klasse vm.Module
bietet eine Low-Level-Schnittstelle zur Verwendung von ECMAScript-Modulen in VM-Kontexten. Sie ist das Gegenstück zur Klasse vm.Script
und spiegelt Moduldatensätze wider, wie sie in der ECMAScript-Spezifikation definiert sind.
Im Gegensatz zu vm.Script
ist jedoch jedes vm.Module
-Objekt von seiner Erstellung an an einen Kontext gebunden. Operationen an vm.Module
-Objekten sind von Natur aus asynchron, im Gegensatz zur synchronen Natur von vm.Script
-Objekten. Die Verwendung von "async"-Funktionen kann bei der Bearbeitung von vm.Module
-Objekten hilfreich sein.
Die Verwendung eines vm.Module
-Objekts erfordert drei verschiedene Schritte: Erstellung/Parsen, Verknüpfung und Auswertung. Diese drei Schritte werden im folgenden Beispiel veranschaulicht.
Diese Implementierung liegt auf einer niedrigeren Ebene als der ECMAScript-Modul-Loader. Es gibt auch noch keine Möglichkeit, mit dem Loader zu interagieren, obwohl Unterstützung geplant ist.
import vm from 'node:vm';
const contextifiedObject = vm.createContext({
secret: 42,
print: console.log,
});
// Step 1
//
// Create a Module by constructing a new `vm.SourceTextModule` object. This
// parses the provided source text, throwing a `SyntaxError` if anything goes
// wrong. By default, a Module is created in the top context. But here, we
// specify `contextifiedObject` as the context this Module belongs to.
//
// Here, we attempt to obtain the default export from the module "foo", and
// put it into local binding "secret".
const bar = new vm.SourceTextModule(`
import s from 'foo';
s;
print(s);
`, { context: contextifiedObject });
// Step 2
//
// "Link" the imported dependencies of this Module to it.
//
// The provided linking callback (the "linker") accepts two arguments: the
// parent module (`bar` in this case) and the string that is the specifier of
// the imported module. The callback is expected to return a Module that
// corresponds to the provided specifier, with certain requirements documented
// in `module.link()`.
//
// If linking has not started for the returned Module, the same linker
// callback will be called on the returned Module.
//
// Even top-level Modules without dependencies must be explicitly linked. The
// callback provided would never be called, however.
//
// The link() method returns a Promise that will be resolved when all the
// Promises returned by the linker resolve.
//
// Note: This is a contrived example in that the linker function creates a new
// "foo" module every time it is called. In a full-fledged module system, a
// cache would probably be used to avoid duplicated modules.
async function linker(specifier, referencingModule) {
if (specifier === 'foo') {
return new vm.SourceTextModule(`
// The "secret" variable refers to the global variable we added to
// "contextifiedObject" when creating the context.
export default secret;
`, { context: referencingModule.context });
// Using `contextifiedObject` instead of `referencingModule.context`
// here would work as well.
}
throw new Error(`Unable to resolve dependency: ${specifier}`);
}
await bar.link(linker);
// Step 3
//
// Evaluate the Module. The evaluate() method returns a promise which will
// resolve after the module has finished evaluating.
// Prints 42.
await bar.evaluate();
const vm = require('node:vm');
const contextifiedObject = vm.createContext({
secret: 42,
print: console.log,
});
(async () => {
// Step 1
//
// Create a Module by constructing a new `vm.SourceTextModule` object. This
// parses the provided source text, throwing a `SyntaxError` if anything goes
// wrong. By default, a Module is created in the top context. But here, we
// specify `contextifiedObject` as the context this Module belongs to.
//
// Here, we attempt to obtain the default export from the module "foo", and
// put it into local binding "secret".
const bar = new vm.SourceTextModule(`
import s from 'foo';
s;
print(s);
`, { context: contextifiedObject });
// Step 2
//
// "Link" the imported dependencies of this Module to it.
//
// The provided linking callback (the "linker") accepts two arguments: the
// parent module (`bar` in this case) and the string that is the specifier of
// the imported module. The callback is expected to return a Module that
// corresponds to the provided specifier, with certain requirements documented
// in `module.link()`.
//
// If linking has not started for the returned Module, the same linker
// callback will be called on the returned Module.
//
// Even top-level Modules without dependencies must be explicitly linked. The
// callback provided would never be called, however.
//
// The link() method returns a Promise that will be resolved when all the
// Promises returned by the linker resolve.
//
// Note: This is a contrived example in that the linker function creates a new
// "foo" module every time it is called. In a full-fledged module system, a
// cache would probably be used to avoid duplicated modules.
async function linker(specifier, referencingModule) {
if (specifier === 'foo') {
return new vm.SourceTextModule(`
// The "secret" variable refers to the global variable we added to
// "contextifiedObject" when creating the context.
export default secret;
`, { context: referencingModule.context });
// Using `contextifiedObject` instead of `referencingModule.context`
// here would work as well.
}
throw new Error(`Unable to resolve dependency: ${specifier}`);
}
await bar.link(linker);
// Step 3
//
// Evaluate the Module. The evaluate() method returns a promise which will
// resolve after the module has finished evaluating.
// Prints 42.
await bar.evaluate();
})();
module.dependencySpecifiers
Die Spezifizierer aller Abhängigkeiten dieses Moduls. Das zurückgegebene Array ist eingefroren, um Änderungen daran zu verhindern.
Entspricht dem Feld [[RequestedModules]]
von Cyclic Module Records in der ECMAScript-Spezifikation.
module.error
Wenn der module.status
'errored'
ist, enthält diese Eigenschaft die Ausnahme, die während der Auswertung vom Modul ausgelöst wurde. Wenn der Status etwas anderes ist, führt der Zugriff auf diese Eigenschaft zu einer ausgelösten Ausnahme.
Der Wert undefined
kann nicht für Fälle verwendet werden, in denen es keine ausgelöste Ausnahme gibt, da dies zu einer möglichen Mehrdeutigkeit mit throw undefined;
führen könnte.
Entspricht dem Feld [[EvaluationError]]
von Cyclic Module Records in der ECMAScript-Spezifikation.
module.evaluate([options])
options
<Object>timeout
<integer> Gibt die Anzahl der Millisekunden an, die vor dem Beenden der Ausführung ausgewertet werden sollen. Wenn die Ausführung unterbrochen wird, wird einError
ausgelöst. Dieser Wert muss eine strikt positive ganze Zahl sein.breakOnSigint
<boolean> Wenntrue
, beendet der Empfang vonSIGINT
(+) die Ausführung und löst einenError
aus. Vorhandene Handler für das Ereignis, die überprocess.on('SIGINT')
angehängt wurden, werden während der Skriptausführung deaktiviert, funktionieren aber danach weiter. Standard:false
.
Gibt zurück: <Promise> Wird bei Erfolg mit
undefined
erfüllt.
Werten Sie das Modul aus.
Dies muss aufgerufen werden, nachdem das Modul verknüpft wurde; andernfalls wird es abgelehnt. Es könnte auch aufgerufen werden, wenn das Modul bereits ausgewertet wurde. In diesem Fall wird entweder nichts unternommen, wenn die anfängliche Auswertung erfolgreich war (module.status
ist 'evaluated'
), oder die Ausnahme wird erneut ausgelöst, die die anfängliche Auswertung verursacht hat (module.status
ist 'errored'
).
Diese Methode kann nicht aufgerufen werden, während das Modul ausgewertet wird (module.status
ist 'evaluating'
).
Entspricht dem Evaluate() concrete method Feld von Cyclic Module Records in der ECMAScript-Spezifikation.
module.identifier
Der Bezeichner des aktuellen Moduls, wie im Konstruktor festgelegt.
module.link(linker)
[Historie]
Version | Änderungen |
---|---|
v21.1.0, v20.10.0, v18.19.0 | Die Option extra.assert wurde in extra.attributes umbenannt. Der frühere Name wird weiterhin zur Abwärtskompatibilität bereitgestellt. |
linker
<Function>specifier
<string> Der Spezifizierer des angeforderten Moduls:referencingModule
<vm.Module> DasModule
-Objekt, für daslink()
aufgerufen wird.extra
<Object>attributes
<Object> Die Daten aus dem Attribut: Gemäß ECMA-262 wird von Hosts erwartet, dass sie einen Fehler auslösen, wenn ein nicht unterstütztes Attribut vorhanden ist.assert
<Object> Alias fürextra.attributes
.Returns: <vm.Module> | <Promise>
Returns: <Promise>
Verknüpft Modulabhängigkeiten. Diese Methode muss vor der Auswertung aufgerufen werden und kann nur einmal pro Modul aufgerufen werden.
Es wird erwartet, dass die Funktion ein Module
-Objekt oder ein Promise
zurückgibt, das letztendlich zu einem Module
-Objekt aufgelöst wird. Das zurückgegebene Module
muss die folgenden zwei Invarianten erfüllen:
- Es muss zum gleichen Kontext wie das übergeordnete
Module
gehören. - Sein
status
darf nicht'errored'
sein.
Wenn der status
des zurückgegebenen Module
'unlinked'
ist, wird diese Methode rekursiv auf dem zurückgegebenen Module
mit derselben bereitgestellten linker
-Funktion aufgerufen.
link()
gibt ein Promise
zurück, das entweder aufgelöst wird, wenn alle Verknüpfungsinstanzen zu einem gültigen Module
aufgelöst werden, oder abgelehnt wird, wenn die Linker-Funktion entweder eine Ausnahme auslöst oder ein ungültiges Module
zurückgibt.
Die Linker-Funktion entspricht ungefähr der implementierungsdefinierten abstrakten Operation HostResolveImportedModule in der ECMAScript-Spezifikation, mit einigen wesentlichen Unterschieden:
- Die Linker-Funktion darf asynchron sein, während HostResolveImportedModule synchron ist.
Die tatsächliche HostResolveImportedModule-Implementierung, die während der Modulverknüpfung verwendet wird, gibt die während der Verknüpfung verknüpften Module zurück. Da zu diesem Zeitpunkt bereits alle Module vollständig verknüpft wären, ist die HostResolveImportedModule-Implementierung gemäß Spezifikation vollständig synchron.
Entspricht dem Feld Link() concrete method von Cyclic Module Records in der ECMAScript-Spezifikation.
module.namespace
Das Namespace-Objekt des Moduls. Dies ist erst verfügbar, nachdem das Verknüpfen (module.link()
) abgeschlossen ist.
Entspricht der abstrakten Operation GetModuleNamespace in der ECMAScript-Spezifikation.
module.status
Der aktuelle Status des Moduls. Kann einer der folgenden Werte sein:
'unlinked'
:module.link()
wurde noch nicht aufgerufen.'linking'
:module.link()
wurde aufgerufen, aber noch nicht alle von der Linker-Funktion zurückgegebenen Promises wurden aufgelöst.'linked'
: Das Modul wurde erfolgreich verknüpft, und alle seine Abhängigkeiten sind verknüpft, abermodule.evaluate()
wurde noch nicht aufgerufen.'evaluating'
: Das Modul wird durch einmodule.evaluate()
auf sich selbst oder ein übergeordnetes Modul ausgewertet.'evaluated'
: Das Modul wurde erfolgreich ausgewertet.'errored'
: Das Modul wurde ausgewertet, aber eine Ausnahme wurde ausgelöst.
Abgesehen von 'errored'
entspricht diese Statuszeichenfolge dem Feld [[Status]]
des Cyclic Module Record der Spezifikation. 'errored'
entspricht 'evaluated'
in der Spezifikation, jedoch mit [[EvaluationError]]
auf einen Wert ungleich undefined
gesetzt.
Klasse: vm.SourceTextModule
Hinzugefügt in: v9.6.0
[Stabil: 1 - Experimentell]
Stabil: 1 Stabilität: 1 - Experimentell
Dieses Feature ist nur mit dem aktivierten Befehlsflag --experimental-vm-modules
verfügbar.
- Erweitert: <vm.Module>
Die Klasse vm.SourceTextModule
stellt den Source Text Module Record bereit, wie er in der ECMAScript-Spezifikation definiert ist.
new vm.SourceTextModule(code[, options])
[Verlauf]
Version | Änderungen |
---|---|
v17.0.0, v16.12.0 | Unterstützung für Importattribute zum Parameter importModuleDynamically hinzugefügt. |
code
<string> JavaScript-Modulcode zum Parsenoptions
identifier
<string> Zeichenkette, die in Stacktraces verwendet wird. Standard:'vm:module(i)'
, wobeii
ein kontextspezifischer aufsteigender Index ist.cachedData
<Buffer> | <TypedArray> | <DataView> Stellt optional einenBuffer
oderTypedArray
oderDataView
mit den Code-Cache-Daten von V8 für die bereitgestellte Quelle bereit. Dercode
muss derselbe sein wie das Modul, aus dem diesecachedData
erstellt wurde.context
<Object> Das kontextgebundene Objekt, das von der Methodevm.createContext()
zurückgegeben wird, um diesesModule
zu kompilieren und auszuwerten. Wenn kein Kontext angegeben ist, wird das Modul im aktuellen Ausführungskontext ausgewertet.lineOffset
<integer> Gibt den Zeilennummernoffset an, der in Stacktraces angezeigt wird, die von diesemModule
erzeugt werden. Standard:0
.columnOffset
<integer> Gibt den Spaltennummernoffset der ersten Zeile an, der in Stacktraces angezeigt wird, die von diesemModule
erzeugt werden. Standard:0
.initializeImportMeta
<Function> Wird während der Auswertung diesesModule
aufgerufen, um dasimport.meta
zu initialisieren.meta
<import.meta>module
<vm.SourceTextModule>importModuleDynamically
<Function> Wird verwendet, um anzugeben, wie die Module während der Auswertung dieses Moduls geladen werden sollen, wennimport()
aufgerufen wird. Diese Option ist Teil der experimentellen Module-API. Wir empfehlen nicht, sie in einer Produktionsumgebung zu verwenden. Detaillierte Informationen finden Sie unter Unterstützung von dynamischemimport()
in Kompilierungs-APIs.
Erstellt eine neue SourceTextModule
-Instanz.
Eigenschaften, die dem Objekt import.meta
zugewiesen werden und Objekte sind, können dem Modul den Zugriff auf Informationen außerhalb des angegebenen context
ermöglichen. Verwenden Sie vm.runInContext()
, um Objekte in einem bestimmten Kontext zu erstellen.
import vm from 'node:vm';
const contextifiedObject = vm.createContext({ secret: 42 });
const module = new vm.SourceTextModule(
'Object.getPrototypeOf(import.meta.prop).secret = secret;',
{
initializeImportMeta(meta) {
// Note: this object is created in the top context. As such,
// Object.getPrototypeOf(import.meta.prop) points to the
// Object.prototype in the top context rather than that in
// the contextified object.
meta.prop = {};
},
});
// Since module has no dependencies, the linker function will never be called.
await module.link(() => {});
await module.evaluate();
// Now, Object.prototype.secret will be equal to 42.
//
// To fix this problem, replace
// meta.prop = {};
// above with
// meta.prop = vm.runInContext('{}', contextifiedObject);
const vm = require('node:vm');
const contextifiedObject = vm.createContext({ secret: 42 });
(async () => {
const module = new vm.SourceTextModule(
'Object.getPrototypeOf(import.meta.prop).secret = secret;',
{
initializeImportMeta(meta) {
// Note: this object is created in the top context. As such,
// Object.getPrototypeOf(import.meta.prop) points to the
// Object.prototype in the top context rather than that in
// the contextified object.
meta.prop = {};
},
});
// Since module has no dependencies, the linker function will never be called.
await module.link(() => {});
await module.evaluate();
// Now, Object.prototype.secret will be equal to 42.
//
// To fix this problem, replace
// meta.prop = {};
// above with
// meta.prop = vm.runInContext('{}', contextifiedObject);
})();
sourceTextModule.createCachedData()
Hinzugefügt in: v13.7.0, v12.17.0
- Gibt zurück: <Buffer>
Erstellt einen Code-Cache, der mit der Option cachedData
des Konstruktors SourceTextModule
verwendet werden kann. Gibt einen Buffer
zurück. Diese Methode kann beliebig oft aufgerufen werden, bevor das Modul ausgewertet wurde.
Der Code-Cache des SourceTextModule
enthält keine JavaScript-beobachtbaren Zustände. Der Code-Cache kann sicher zusammen mit dem Skript-Sourcecode gespeichert und verwendet werden, um mehrmals neue SourceTextModule
-Instanzen zu erstellen.
Funktionen in der SourceTextModule
-Quelle können als verzögert kompiliert markiert werden und werden nicht bei der Erstellung des SourceTextModule
kompiliert. Diese Funktionen werden kompiliert, wenn sie zum ersten Mal aufgerufen werden. Der Code-Cache serialisiert die Metadaten, die V8 derzeit über das SourceTextModule
kennt und die zur Beschleunigung zukünftiger Kompilierungen verwendet werden können.
// Erstellen Sie ein anfängliches Modul
const module = new vm.SourceTextModule('const a = 1;');
// Erstellen Sie einen gecachten Datensatz aus diesem Modul
const cachedData = module.createCachedData();
// Erstellen Sie ein neues Modul mit den gecachten Daten. Der Code muss derselbe sein.
const module2 = new vm.SourceTextModule('const a = 1;', { cachedData });
Klasse: vm.SyntheticModule
Hinzugefügt in: v13.0.0, v12.16.0
[Stabil: 1 - Experimentell]
Stabil: 1 Stabilität: 1 - Experimentell
Diese Funktion ist nur mit dem Befehlszeilenparameter --experimental-vm-modules
aktiviert.
- Erweitert: <vm.Module>
Die Klasse vm.SyntheticModule
stellt den Synthetic Module Record bereit, wie er in der WebIDL-Spezifikation definiert ist. Der Zweck synthetischer Module ist die Bereitstellung einer generischen Schnittstelle zum Bereitstellen von Nicht-JavaScript-Quellen für ECMAScript-Modulgraphen.
const vm = require('node:vm');
const source = '{ "a": 1 }';
const module = new vm.SyntheticModule(['default'], function() {
const obj = JSON.parse(source);
this.setExport('default', obj);
});
// Verwenden Sie `module` in der Verknüpfung...
new vm.SyntheticModule(exportNames, evaluateCallback[, options])
Hinzugefügt in: v13.0.0, v12.16.0
exportNames
<string[]> Array von Namen, die aus dem Modul exportiert werden.evaluateCallback
<Function> Wird aufgerufen, wenn das Modul ausgewertet wird.options
identifier
<string> Zeichenkette, die in Stacktraces verwendet wird. Standard:'vm:module(i)'
, wobeii
ein kontextspezifischer aufsteigender Index ist.context
<Object> Das kontextualisierte Objekt, wie es von der Methodevm.createContext()
zurückgegeben wird, um diesesModule
zu kompilieren und auszuwerten.
Erstellt eine neue SyntheticModule
-Instanz.
Objekte, die den Exporten dieser Instanz zugewiesen werden, können es Importeuren des Moduls ermöglichen, auf Informationen außerhalb des angegebenen context
zuzugreifen. Verwenden Sie vm.runInContext()
, um Objekte in einem bestimmten Kontext zu erstellen.
syntheticModule.setExport(name, value)
Hinzugefügt in: v13.0.0, v12.16.0
name
<string> Name des Exports, der gesetzt werden soll.value
<any> Der Wert, auf den der Export gesetzt werden soll.
Diese Methode wird verwendet, nachdem das Modul verknüpft wurde, um die Werte der Exporte festzulegen. Wenn sie aufgerufen wird, bevor das Modul verknüpft ist, wird ein ERR_VM_MODULE_STATUS
-Fehler geworfen.
import vm from 'node:vm';
const m = new vm.SyntheticModule(['x'], () => {
m.setExport('x', 1);
});
await m.link(() => {});
await m.evaluate();
assert.strictEqual(m.namespace.x, 1);
const vm = require('node:vm');
(async () => {
const m = new vm.SyntheticModule(['x'], () => {
m.setExport('x', 1);
});
await m.link(() => {});
await m.evaluate();
assert.strictEqual(m.namespace.x, 1);
})();
vm.compileFunction(code[, params[, options]])
[Verlauf]
Version | Änderungen |
---|---|
v21.7.0, v20.12.0 | Unterstützung für vm.constants.USE_MAIN_CONTEXT_DEFAULT_LOADER hinzugefügt. |
v19.6.0, v18.15.0 | Der Rückgabewert enthält jetzt cachedDataRejected mit der gleichen Semantik wie die vm.Script -Version, wenn die Option cachedData übergeben wurde. |
v17.0.0, v16.12.0 | Unterstützung für Importattribute zum Parameter importModuleDynamically hinzugefügt. |
v15.9.0 | Option importModuleDynamically wieder hinzugefügt. |
v14.3.0 | Entfernung von importModuleDynamically aufgrund von Kompatibilitätsproblemen. |
v14.1.0, v13.14.0 | Die Option importModuleDynamically wird jetzt unterstützt. |
v10.10.0 | Hinzugefügt in: v10.10.0 |
code
<string> Der Hauptteil der zu kompilierenden Funktion.params
<string[]> Ein Array von Strings, das alle Parameter für die Funktion enthält.options
<Object>filename
<string> Gibt den Dateinamen an, der in Stacktraces verwendet wird, die von diesem Skript erzeugt werden. Standard:''
.lineOffset
<number> Gibt den Zeilennummer-Offset an, der in Stacktraces angezeigt wird, die von diesem Skript erzeugt werden. Standard:0
.columnOffset
<number> Gibt den Spaltennummer-Offset der ersten Zeile an, der in Stacktraces angezeigt wird, die von diesem Skript erzeugt werden. Standard:0
.cachedData
<Buffer> | <TypedArray> | <DataView> Stellt einen optionalenBuffer
oderTypedArray
oderDataView
mit V8's Code-Cache-Daten für die bereitgestellte Quelle bereit. Dies muss durch einen vorherigen Aufruf vonvm.compileFunction()
mit demselbencode
undparams
erzeugt werden.produceCachedData
<boolean> Gibt an, ob neue Cache-Daten erzeugt werden sollen. Standard:false
.parsingContext
<Object> Das contextified Objekt, in dem die besagte Funktion kompiliert werden soll.contextExtensions
<Object[]> Ein Array, das eine Sammlung von Kontext-Erweiterungen (Objekte, die den aktuellen Scope umschließen) enthält, die während der Kompilierung angewendet werden sollen. Standard:[]
.
importModuleDynamically
<Function> | <vm.constants.USE_MAIN_CONTEXT_DEFAULT_LOADER> Wird verwendet, um anzugeben, wie die Module während der Auswertung dieser Funktion geladen werden sollen, wennimport()
aufgerufen wird. Diese Option ist Teil der experimentellen Module-API. Wir empfehlen nicht, sie in einer Produktionsumgebung zu verwenden. Detaillierte Informationen finden Sie unter Unterstützung von dynamischemimport()
in Kompilierungs-APIs.Gibt zurück: <Function>
Kompiliert den gegebenen Code in den bereitgestellten Kontext (wenn kein Kontext bereitgestellt wird, wird der aktuelle Kontext verwendet) und gibt ihn verpackt in einer Funktion mit den gegebenen params
zurück.
vm.constants
Hinzugefügt in: v21.7.0, v20.12.0
Gibt ein Objekt zurück, das häufig verwendete Konstanten für VM-Operationen enthält.
vm.constants.USE_MAIN_CONTEXT_DEFAULT_LOADER
Hinzugefügt in: v21.7.0, v20.12.0
[Stabil: 1 - Experimentell]
Stabil: 1 Stabilität: 1.1 - Aktive Entwicklung
Eine Konstante, die als importModuleDynamically
-Option für vm.Script
und vm.compileFunction()
verwendet werden kann, sodass Node.js den Standard-ESM-Loader aus dem Hauptkontext verwendet, um das angeforderte Modul zu laden.
Für detaillierte Informationen siehe Unterstützung von dynamischem import()
in Kompilierungs-APIs.
vm.createContext([contextObject[, options]])
[Verlauf]
Version | Änderungen |
---|---|
v22.8.0, v20.18.0 | Das contextObject -Argument akzeptiert jetzt vm.constants.DONT_CONTEXTIFY . |
v21.7.0, v20.12.0 | Unterstützung für vm.constants.USE_MAIN_CONTEXT_DEFAULT_LOADER hinzugefügt. |
v21.2.0, v20.11.0 | Die importModuleDynamically -Option wird jetzt unterstützt. |
v14.6.0 | Die microtaskMode -Option wird jetzt unterstützt. |
v10.0.0 | Das erste Argument kann nicht mehr eine Funktion sein. |
v10.0.0 | Die codeGeneration -Option wird jetzt unterstützt. |
v0.3.1 | Hinzugefügt in: v0.3.1 |
contextObject
<Object> | <vm.constants.DONT_CONTEXTIFY> | <undefined> Entwedervm.constants.DONT_CONTEXTIFY
oder ein Objekt, das kontextualisiert wird. Wennundefined
, wird ein leeres, kontextualisiertes Objekt zur Rückwärtskompatibilität erstellt.options
<Object>name
<string> Für Menschen lesbarer Name des neu erstellten Kontexts. Standard:'VM Context i'
, wobeii
ein aufsteigender numerischer Index des erstellten Kontexts ist.origin
<string> Ursprung entsprechend dem neu erstellten Kontext für Anzeigezwecke. Der Ursprung sollte wie eine URL formatiert sein, aber nur das Schema, den Host und den Port (falls erforderlich) enthalten, wie der Wert der Eigenschafturl.origin
einesURL
-Objekts. Insbesondere sollte diese Zeichenfolge den abschließenden Schrägstrich weglassen, da dieser einen Pfad bezeichnet. Standard:''
.codeGeneration
<Object>strings
<boolean> Wenn auf false gesetzt, werfen alle Aufrufe voneval
oder Funktionskonstruktoren (Function
,GeneratorFunction
usw.) einenEvalError
. Standard:true
.wasm
<boolean> Wenn auf false gesetzt, wirft jeder Versuch, ein WebAssembly-Modul zu kompilieren, einenWebAssembly.CompileError
. Standard:true
.microtaskMode
<string> Wenn aufafterEvaluate
gesetzt, werden Mikrotasks (Tasks, die überPromise
s undasync function
s geplant werden) unmittelbar nachdem ein Skript überscript.runInContext()
ausgeführt wurde, ausgeführt. Sie sind in diesem Fall in dentimeout
- undbreakOnSigint
-Bereichen enthalten.importModuleDynamically
<Function> | <vm.constants.USE_MAIN_CONTEXT_DEFAULT_LOADER> Wird verwendet, um anzugeben, wie die Module geladen werden sollen, wennimport()
in diesem Kontext ohne ein Referrer-Skript oder -Modul aufgerufen wird. Diese Option ist Teil der experimentellen Module-API. Wir empfehlen, sie nicht in einer Produktionsumgebung zu verwenden. Für detaillierte Informationen siehe Unterstützung von dynamischemimport()
in Kompilierungs-APIs.
Gibt zurück: <Object> kontextualisiertes Objekt.
Wenn das angegebene contextObject
ein Objekt ist, bereitet die Methode vm.createContext()
dieses Objekt vor und gibt einen Verweis darauf zurück, sodass es in Aufrufen von vm.runInContext()
oder script.runInContext()
verwendet werden kann. Innerhalb solcher Skripte wird das globale Objekt vom contextObject
umschlossen, wobei alle seine vorhandenen Eigenschaften beibehalten werden, aber auch die eingebauten Objekte und Funktionen enthalten sind, die jedes Standard-globale Objekt hat. Außerhalb von Skripten, die vom vm-Modul ausgeführt werden, bleiben globale Variablen unverändert.
const vm = require('node:vm');
global.globalVar = 3;
const context = { globalVar: 1 };
vm.createContext(context);
vm.runInContext('globalVar *= 2;', context);
console.log(context);
// Prints: { globalVar: 2 }
console.log(global.globalVar);
// Prints: 3
Wenn contextObject
weggelassen wird (oder explizit als undefined
übergeben wird), wird ein neues, leeres kontextualisiertes Objekt zurückgegeben.
Wenn das globale Objekt im neu erstellten Kontext kontextualisiert wird, weist es einige Besonderheiten im Vergleich zu gewöhnlichen globalen Objekten auf. Zum Beispiel kann es nicht eingefroren werden. Um einen Kontext ohne die Besonderheiten der Kontextualisierung zu erstellen, übergeben Sie vm.constants.DONT_CONTEXTIFY
als das contextObject
-Argument. Siehe die Dokumentation von vm.constants.DONT_CONTEXTIFY
für Details.
Die Methode vm.createContext()
ist in erster Linie nützlich, um einen einzelnen Kontext zu erstellen, der zum Ausführen mehrerer Skripte verwendet werden kann. Wenn beispielsweise ein Webbrowser emuliert wird, kann die Methode verwendet werden, um einen einzelnen Kontext zu erstellen, der das globale Objekt eines Fensters darstellt, und dann alle \<script\>
-Tags zusammen in diesem Kontext auszuführen.
Der bereitgestellte name
und origin
des Kontexts werden über die Inspector-API sichtbar gemacht.
vm.isContext(object)
Hinzugefügt in: v0.11.7
Gibt true
zurück, wenn das gegebene object
Objekt mit vm.createContext()
kontextualisiert wurde oder wenn es sich um das globale Objekt eines Kontexts handelt, der mit vm.constants.DONT_CONTEXTIFY
erstellt wurde.
vm.measureMemory([options])
Hinzugefügt in: v13.10.0
[Stabil: 1 - Experimentell]
Stabil: 1 Stabilität: 1 - Experimentell
Misst den Speicher, der V8 bekannt ist und von allen Kontexten verwendet wird, die der aktuellen V8-Isolierung oder dem Hauptkontext bekannt sind.
options
<Object> Optional.mode
<string> Entweder'summary'
oder'detailed'
. Im Zusammenfassungsmodus wird nur der für den Hauptkontext gemessene Speicher zurückgegeben. Im detaillierten Modus wird der für alle Kontexte gemessene Speicher zurückgegeben, die der aktuellen V8-Isolierung bekannt sind. Standard:'summary'
execution
<string> Entweder'default'
oder'eager'
. Bei der Standardausführung wird das Promise erst dann aufgelöst, nachdem die nächste geplante Garbage Collection gestartet wurde, was eine Weile dauern kann (oder nie, wenn das Programm vor der nächsten GC beendet wird). Bei der sofortigen Ausführung wird die GC sofort gestartet, um den Speicher zu messen. Standard:'default'
Gibt zurück: <Promise> Wenn der Speicher erfolgreich gemessen wurde, wird das Promise mit einem Objekt aufgelöst, das Informationen zur Speichernutzung enthält. Andernfalls wird es mit einem
ERR_CONTEXT_NOT_INITIALIZED
-Fehler abgelehnt.
Das Format des Objekts, mit dem das zurückgegebene Promise möglicherweise aufgelöst wird, ist spezifisch für die V8-Engine und kann sich von einer Version von V8 zur nächsten ändern.
Das zurückgegebene Ergebnis unterscheidet sich von den Statistiken, die von v8.getHeapSpaceStatistics()
zurückgegeben werden, darin, dass vm.measureMemory()
den Speicher misst, der von jedem V8-spezifischen Kontext in der aktuellen Instanz der V8-Engine erreichbar ist, während das Ergebnis von v8.getHeapSpaceStatistics()
den Speicher misst, der von jedem Heap-Bereich in der aktuellen V8-Instanz belegt wird.
const vm = require('node:vm');
// Misst den vom Hauptkontext verwendeten Speicher.
vm.measureMemory({ mode: 'summary' })
// Dies ist das Gleiche wie vm.measureMemory()
.then((result) => {
// Das aktuelle Format ist:
// {
// total: {
// jsMemoryEstimate: 2418479, jsMemoryRange: [ 2418479, 2745799 ]
// }
// }
console.log(result);
});
const context = vm.createContext({ a: 1 });
vm.measureMemory({ mode: 'detailed', execution: 'eager' })
.then((result) => {
// Referenzieren Sie den Kontext hier, damit er nicht GC'ed wird
// bis die Messung abgeschlossen ist.
console.log(context.a);
// {
// total: {
// jsMemoryEstimate: 2574732,
// jsMemoryRange: [ 2574732, 2904372 ]
// },
// current: {
// jsMemoryEstimate: 2438996,
// jsMemoryRange: [ 2438996, 2768636 ]
// },
// other: [
// {
// jsMemoryEstimate: 135736,
// jsMemoryRange: [ 135736, 465376 ]
// }
// ]
// }
console.log(result);
});
vm.runInContext(code, contextifiedObject[, options])
[Verlauf]
Version | Änderungen |
---|---|
v21.7.0, v20.12.0 | Unterstützung für vm.constants.USE_MAIN_CONTEXT_DEFAULT_LOADER hinzugefügt. |
v17.0.0, v16.12.0 | Unterstützung für Importattribute zum Parameter importModuleDynamically hinzugefügt. |
v6.3.0 | Die Option breakOnSigint wird jetzt unterstützt. |
v0.3.1 | Hinzugefügt in: v0.3.1 |
code
<string> Der JavaScript-Code, der kompiliert und ausgeführt werden soll.contextifiedObject
<Object> Das kontextualisierte Objekt, das alsglobal
verwendet wird, wenn dercode
kompiliert und ausgeführt wird.options
<Object> | <string>filename
<string> Gibt den Dateinamen an, der in Stacktraces verwendet wird, die von diesem Skript erzeugt werden. Standard:'evalmachine.\<anonymous\>'
.lineOffset
<number> Gibt den Zeilennummer-Offset an, der in Stacktraces angezeigt wird, die von diesem Skript erzeugt werden. Standard:0
.columnOffset
<number> Gibt den Spaltennummer-Offset der ersten Zeile an, der in Stacktraces angezeigt wird, die von diesem Skript erzeugt werden. Standard:0
.displayErrors
<boolean> Wenntrue
, wird die Codezeile, die den Fehler verursacht, an den Stacktrace angehängt, falls einError
während der Kompilierung descode
auftritt. Standard:true
.timeout
<integer> Gibt die Anzahl der Millisekunden an, diecode
ausgeführt werden soll, bevor die Ausführung beendet wird. Wenn die Ausführung beendet wird, wird einError
ausgelöst. Dieser Wert muss eine strikt positive ganze Zahl sein.breakOnSigint
<boolean> Wenntrue
, beendet der Empfang vonSIGINT
(+) die Ausführung und löst einenError
aus. Vorhandene Handler für das Ereignis, die überprocess.on('SIGINT')
angehängt wurden, werden während der Skriptausführung deaktiviert, funktionieren aber danach weiterhin. Standard:false
.cachedData
<Buffer> | <TypedArray> | <DataView> Stellt optional einenBuffer
oderTypedArray
oderDataView
mit V8's Code-Cache-Daten für die bereitgestellte Quelle bereit.importModuleDynamically
<Function> | <vm.constants.USE_MAIN_CONTEXT_DEFAULT_LOADER> Wird verwendet, um anzugeben, wie die Module während der Auswertung dieses Skripts geladen werden sollen, wennimport()
aufgerufen wird. Diese Option ist Teil der experimentellen Module-API. Wir empfehlen, sie nicht in einer Produktionsumgebung zu verwenden. Detaillierte Informationen finden Sie unter Unterstützung von dynamischemimport()
in Kompilierungs-APIs.
Die Methode vm.runInContext()
kompiliert code
, führt es im Kontext des contextifiedObject
aus und gibt dann das Ergebnis zurück. Der ausgeführte Code hat keinen Zugriff auf den lokalen Gültigkeitsbereich. Das contextifiedObject
-Objekt muss zuvor mit der Methode vm.createContext()
kontextualisiert worden sein.
Wenn options
ein String ist, gibt er den Dateinamen an.
Das folgende Beispiel kompiliert und führt verschiedene Skripte mit einem einzigen kontextualisierten Objekt aus:
const vm = require('node:vm');
const contextObject = { globalVar: 1 };
vm.createContext(contextObject);
for (let i = 0; i < 10; ++i) {
vm.runInContext('globalVar *= 2;', contextObject);
}
console.log(contextObject);
// Prints: { globalVar: 1024 }
vm.runInNewContext(code[, contextObject[, options]])
[Verlauf]
Version | Änderungen |
---|---|
v22.8.0, v20.18.0 | Das Argument contextObject akzeptiert jetzt vm.constants.DONT_CONTEXTIFY . |
v21.7.0, v20.12.0 | Unterstützung für vm.constants.USE_MAIN_CONTEXT_DEFAULT_LOADER hinzugefügt. |
v17.0.0, v16.12.0 | Unterstützung für Importattribute für den Parameter importModuleDynamically hinzugefügt. |
v14.6.0 | Die Option microtaskMode wird jetzt unterstützt. |
v10.0.0 | Die Option contextCodeGeneration wird jetzt unterstützt. |
v6.3.0 | Die Option breakOnSigint wird jetzt unterstützt. |
v0.3.1 | Hinzugefügt in: v0.3.1 |
code
<string> Der zu kompilierende und auszuführende JavaScript-Code.contextObject
<Object> | <vm.constants.DONT_CONTEXTIFY> | <undefined> Entwedervm.constants.DONT_CONTEXTIFY
oder ein Objekt, das kontextifiziert wird. Wennundefined
, wird ein leeres kontextifiziertes Objekt zur Abwärtskompatibilität erstellt.filename
<string> Gibt den Dateinamen an, der in Stacktraces verwendet wird, die von diesem Skript erzeugt werden. Standard:'evalmachine.\<anonymous\>'
.lineOffset
<number> Gibt den Zeilennummer-Offset an, der in Stacktraces angezeigt wird, die von diesem Skript erzeugt werden. Standard:0
.columnOffset
<number> Gibt den Spaltennummer-Offset der ersten Zeile an, der in Stacktraces angezeigt wird, die von diesem Skript erzeugt werden. Standard:0
.displayErrors
<boolean> Wenntrue
, wird bei einemError
beim Kompilieren descode
die Codezeile, die den Fehler verursacht, an den Stacktrace angehängt. Standard:true
.timeout
<integer> Gibt die Anzahl der Millisekunden an, diecode
ausgeführt wird, bevor die Ausführung beendet wird. Wenn die Ausführung beendet wird, wird einError
ausgelöst. Dieser Wert muss eine strikt positive ganze Zahl sein.breakOnSigint
<boolean> Wenntrue
, beendet der Empfang vonSIGINT
(+) die Ausführung und löst einError
aus. Vorhandene Handler für das Ereignis, die überprocess.on('SIGINT')
angehängt wurden, werden während der Skriptausführung deaktiviert, funktionieren aber danach weiter. Standard:false
.contextName
<string> Für Menschen lesbarer Name des neu erstellten Kontexts. Standard:'VM Kontext i'
, wobeii
ein aufsteigender numerischer Index des erstellten Kontexts ist.contextOrigin
<string> Ursprung, der dem neu erstellten Kontext zu Anzeigezwecken entspricht. Der Ursprung sollte wie eine URL formatiert sein, aber nur mit dem Schema, dem Host und dem Port (falls erforderlich), wie der Wert der Eigenschafturl.origin
einesURL
-Objekts. Insbesondere sollte diese Zeichenkette den nachgestellten Schrägstrich weglassen, da dies einen Pfad bezeichnet. Standard:''
.contextCodeGeneration
<Object>strings
<boolean> Wenn auf false gesetzt, lösen alle Aufrufe voneval
oder Funktionskonstruktoren (Function
,GeneratorFunction
, etc.) einenEvalError
aus. Standard:true
.wasm
<boolean> Wenn auf false gesetzt, löst jeder Versuch, ein WebAssembly-Modul zu kompilieren, einenWebAssembly.CompileError
aus. Standard:true
.cachedData
<Buffer> | <TypedArray> | <DataView> Bietet einen optionalenBuffer
oderTypedArray
oderDataView
mit den Code-Cache-Daten von V8 für die bereitgestellte Quelle.importModuleDynamically
<Function> | <vm.constants.USE_MAIN_CONTEXT_DEFAULT_LOADER> Wird verwendet, um anzugeben, wie die Module während der Auswertung dieses Skripts geladen werden sollen, wennimport()
aufgerufen wird. Diese Option ist Teil der experimentellen Module-API. Wir empfehlen, sie nicht in einer Produktionsumgebung zu verwenden. Detaillierte Informationen finden Sie unter Unterstützung von dynamischemimport()
in Kompilierungs-APIs.microtaskMode
<string> Wenn aufafterEvaluate
gesetzt, werden Microtasks (Tasks, die überPromise
s undasync function
s geplant werden) unmittelbar nach der Ausführung des Skripts ausgeführt. Sie sind in diesem Fall in den Geltungsbereichentimeout
undbreakOnSigint
enthalten.
Gibt zurück: <any> das Ergebnis der allerletzten Anweisung, die im Skript ausgeführt wurde.
Diese Methode ist eine Abkürzung für (new vm.Script(code, options)).runInContext(vm.createContext(options), options)
. Wenn options
ein String ist, gibt er den Dateinamen an.
Sie macht mehrere Dinge gleichzeitig:
Das folgende Beispiel kompiliert und führt Code aus, der eine globale Variable inkrementiert und eine neue setzt. Diese globalen Variablen sind im contextObject
enthalten.
const vm = require('node:vm');
const contextObject = {
animal: 'cat',
count: 2,
};
vm.runInNewContext('count += 1; name = "kitty"', contextObject);
console.log(contextObject);
// Prints: { animal: 'cat', count: 3, name: 'kitty' }
// Dies würde einen Fehler auslösen, wenn der Kontext aus einem kontextifizierten Objekt erstellt wird.
// vm.constants.DONT_CONTEXTIFY ermöglicht das Erstellen von Kontexten mit gewöhnlichen globalen Objekten, die
// eingefroren werden können.
const frozenContext = vm.runInNewContext('Object.freeze(globalThis); globalThis;', vm.constants.DONT_CONTEXTIFY);
vm.runInThisContext(code[, options])
[Verlauf]
Version | Änderungen |
---|---|
v21.7.0, v20.12.0 | Unterstützung für vm.constants.USE_MAIN_CONTEXT_DEFAULT_LOADER hinzugefügt. |
v17.0.0, v16.12.0 | Unterstützung für Importattribute für den Parameter importModuleDynamically hinzugefügt. |
v6.3.0 | Die Option breakOnSigint wird jetzt unterstützt. |
v0.3.1 | Hinzugefügt in: v0.3.1 |
code
<string> Der zu kompilierende und auszuführende JavaScript-Code.filename
<string> Gibt den Dateinamen an, der in Stacktraces verwendet wird, die von diesem Skript erzeugt werden. Standard:'evalmachine.\<anonymous\>'
.lineOffset
<number> Gibt den Zeilennummer-Offset an, der in Stacktraces angezeigt wird, die von diesem Skript erzeugt werden. Standard:0
.columnOffset
<number> Gibt den Spaltennummer-Offset der ersten Zeile an, der in Stacktraces angezeigt wird, die von diesem Skript erzeugt werden. Standard:0
.displayErrors
<boolean> Wenntrue
, wird die Codezeile, die den Fehler verursacht, an den Stacktrace angehängt, wenn beim Kompilieren descode
einError
auftritt. Standard:true
.timeout
<integer> Gibt die Anzahl der Millisekunden an, diecode
ausgeführt werden soll, bevor die Ausführung beendet wird. Wenn die Ausführung beendet wird, wird einError
ausgelöst. Dieser Wert muss eine strikt positive ganze Zahl sein.breakOnSigint
<boolean> Wenntrue
, beendet der Empfang vonSIGINT
(+) die Ausführung und löst einenError
aus. Vorhandene Handler für das Ereignis, die überprocess.on('SIGINT')
angehängt wurden, werden während der Skriptausführung deaktiviert, funktionieren aber danach weiter. Standard:false
.cachedData
<Buffer> | <TypedArray> | <DataView> Bietet einen optionalenBuffer
oderTypedArray
oderDataView
mit den Code-Cache-Daten von V8 für die bereitgestellte Quelle.importModuleDynamically
<Function> | <vm.constants.USE_MAIN_CONTEXT_DEFAULT_LOADER> Wird verwendet, um anzugeben, wie die Module während der Auswertung dieses Skripts geladen werden sollen, wennimport()
aufgerufen wird. Diese Option ist Teil der experimentellen Modul-API. Wir empfehlen, sie nicht in einer Produktionsumgebung zu verwenden. Detaillierte Informationen finden Sie unter Unterstützung von dynamischemimport()
in Kompilierungs-APIs.
Returns: <any> Das Ergebnis der allerletzten Anweisung, die im Skript ausgeführt wurde.
vm.runInThisContext()
kompiliert code
, führt es im Kontext des aktuellen global
aus und gibt das Ergebnis zurück. Der ausgeführte Code hat keinen Zugriff auf den lokalen Scope, hat aber Zugriff auf das aktuelle global
-Objekt.
Wenn options
ein String ist, dann gibt er den Dateinamen an.
Das folgende Beispiel veranschaulicht die Verwendung von vm.runInThisContext()
und der JavaScript-Funktion eval()
, um denselben Code auszuführen:
const vm = require('node:vm');
let localVar = 'initial value';
const vmResult = vm.runInThisContext('localVar = "vm";');
console.log(`vmResult: '${vmResult}', localVar: '${localVar}'`);
// Prints: vmResult: 'vm', localVar: 'initial value'
const evalResult = eval('localVar = "eval";');
console.log(`evalResult: '${evalResult}', localVar: '${localVar}'`);
// Prints: evalResult: 'eval', localVar: 'eval'
Da vm.runInThisContext()
keinen Zugriff auf den lokalen Scope hat, bleibt localVar
unverändert. Im Gegensatz dazu hat eval()
tatsächlich Zugriff auf den lokalen Scope, sodass der Wert localVar
geändert wird. Auf diese Weise ähnelt vm.runInThisContext()
einem indirekten eval()
-Aufruf, z.B. (0,eval)('code')
.
Beispiel: Ausführen eines HTTP-Servers innerhalb einer VM
Bei Verwendung von script.runInThisContext()
oder vm.runInThisContext()
wird der Code im aktuellen globalen V8-Kontext ausgeführt. Der an diesen VM-Kontext übergebene Code hat seinen eigenen isolierten Gültigkeitsbereich.
Um einen einfachen Webserver mit dem Modul node:http
auszuführen, muss der an den Kontext übergebene Code entweder require('node:http')
selbst aufrufen oder einen Verweis auf das Modul node:http
übergeben bekommen. Zum Beispiel:
'use strict';
const vm = require('node:vm');
const code = `
((require) => {
const http = require('node:http');
http.createServer((request, response) => {
response.writeHead(200, { 'Content-Type': 'text/plain' });
response.end('Hello World\\n');
}).listen(8124);
console.log('Server running at http://127.0.0.1:8124/');
})`;
vm.runInThisContext(code)(require);
Der require()
im obigen Fall teilt sich den Zustand mit dem Kontext, aus dem er übergeben wird. Dies kann Risiken bergen, wenn nicht vertrauenswürdiger Code ausgeführt wird, z. B. wenn Objekte im Kontext auf unerwünschte Weise verändert werden.
Was bedeutet es, ein Objekt zu "kontextualisieren"?
Jegliches JavaScript, das innerhalb von Node.js ausgeführt wird, läuft im Gültigkeitsbereich eines "Kontexts". Laut V8 Embedder's Guide:
Wenn die Methode vm.createContext()
mit einem Objekt aufgerufen wird, wird das Argument contextObject
verwendet, um das globale Objekt einer neuen Instanz eines V8-Kontexts einzuschließen (wenn contextObject
undefined
ist, wird ein neues Objekt aus dem aktuellen Kontext erstellt, bevor es kontextualisiert wird). Dieser V8-Kontext stellt den code
, der mit den Methoden des Moduls node:vm
ausgeführt wird, mit einer isolierten globalen Umgebung bereit, in der er arbeiten kann. Der Prozess der Erstellung des V8-Kontexts und dessen Verknüpfung mit dem contextObject
im äußeren Kontext wird in diesem Dokument als "Kontextualisierung" des Objekts bezeichnet.
Die Kontextualisierung würde einige Eigenheiten in den globalThis
-Wert im Kontext einführen. Zum Beispiel kann er nicht eingefroren werden und er ist nicht referenziell gleich dem contextObject
im äußeren Kontext.
const vm = require('node:vm');
// Eine undefinierte `contextObject`-Option sorgt dafür, dass das globale Objekt kontextualisiert wird.
const context = vm.createContext();
console.log(vm.runInContext('globalThis', context) === context); // false
// Ein kontextualisiertes globales Objekt kann nicht eingefroren werden.
try {
vm.runInContext('Object.freeze(globalThis);', context);
} catch (e) {
console.log(e); // TypeError: Cannot freeze
}
console.log(vm.runInContext('globalThis.foo = 1; foo;', context)); // 1
Um einen Kontext mit einem gewöhnlichen globalen Objekt zu erstellen und im äußeren Kontext auf einen globalen Proxy mit weniger Eigenheiten zuzugreifen, geben Sie vm.constants.DONT_CONTEXTIFY
als Argument contextObject
an.
vm.constants.DONT_CONTEXTIFY
Wenn diese Konstante als contextObject
-Argument in VM-APIs verwendet wird, weist sie Node.js an, einen Kontext zu erstellen, ohne sein globales Objekt auf Node.js-spezifische Weise mit einem anderen Objekt zu umschließen. Infolgedessen würde sich der Wert globalThis
innerhalb des neuen Kontexts eher wie ein gewöhnlicher verhalten.
const vm = require('node:vm');
// Verwenden Sie vm.constants.DONT_CONTEXTIFY, um das globale Objekt einzufrieren.
const context = vm.createContext(vm.constants.DONT_CONTEXTIFY);
vm.runInContext('Object.freeze(globalThis);', context);
try {
vm.runInContext('bar = 1; bar;', context);
} catch (e) {
console.log(e); // Uncaught ReferenceError: bar is not defined
}
Wenn vm.constants.DONT_CONTEXTIFY
als contextObject
-Argument für vm.createContext()
verwendet wird, ist das zurückgegebene Objekt ein Proxy-ähnliches Objekt für das globale Objekt im neu erstellten Kontext mit weniger Node.js-spezifischen Eigenheiten. Es ist referenzgleich zum Wert globalThis
im neuen Kontext, kann von außerhalb des Kontexts geändert werden und kann verwendet werden, um direkt auf Built-Ins im neuen Kontext zuzugreifen.
const vm = require('node:vm');
const context = vm.createContext(vm.constants.DONT_CONTEXTIFY);
// Das zurückgegebene Objekt ist referenzgleich zu globalThis im neuen Kontext.
console.log(vm.runInContext('globalThis', context) === context); // true
// Kann verwendet werden, um direkt auf Globale im neuen Kontext zuzugreifen.
console.log(context.Array); // [Function: Array]
vm.runInContext('foo = 1;', context);
console.log(context.foo); // 1
context.bar = 1;
console.log(vm.runInContext('bar;', context)); // 1
// Kann eingefroren werden und beeinflusst den inneren Kontext.
Object.freeze(context);
try {
vm.runInContext('baz = 1; baz;', context);
} catch (e) {
console.log(e); // Uncaught ReferenceError: baz is not defined
}
Timeout-Interaktionen mit asynchronen Aufgaben und Promises
Promise
s und async function
s können Aufgaben planen, die von der JavaScript-Engine asynchron ausgeführt werden. Standardmäßig werden diese Aufgaben ausgeführt, nachdem alle JavaScript-Funktionen im aktuellen Stack ausgeführt wurden. Dies ermöglicht das Umgehen der Funktionalität der Optionen timeout
und breakOnSigint
.
Der folgende Code, der von vm.runInNewContext()
mit einem Timeout von 5 Millisekunden ausgeführt wird, plant beispielsweise eine Endlosschleife, die nach der Auflösung eines Promises ausgeführt wird. Die geplante Schleife wird nie durch das Timeout unterbrochen:
const vm = require('node:vm');
function loop() {
console.log('entering loop');
while (1) console.log(Date.now());
}
vm.runInNewContext(
'Promise.resolve().then(() => loop());',
{ loop, console },
{ timeout: 5 },
);
// Dies wird *vor* 'entering loop' ausgegeben (!)
console.log('done executing');
Dies kann behoben werden, indem microtaskMode: 'afterEvaluate'
an den Code übergeben wird, der den Context
erstellt:
const vm = require('node:vm');
function loop() {
while (1) console.log(Date.now());
}
vm.runInNewContext(
'Promise.resolve().then(() => loop());',
{ loop, console },
{ timeout: 5, microtaskMode: 'afterEvaluate' },
);
In diesem Fall wird die über promise.then()
geplante Microtask ausgeführt, bevor von vm.runInNewContext()
zurückgekehrt wird, und wird durch die timeout
-Funktionalität unterbrochen. Dies gilt nur für Code, der in einem vm.Context
ausgeführt wird, sodass z. B. vm.runInThisContext()
diese Option nicht akzeptiert.
Promise-Callbacks werden in die Microtask-Warteschlange des Kontexts eingetragen, in dem sie erstellt wurden. Wenn beispielsweise () =\> loop()
im obigen Beispiel durch nur loop
ersetzt wird, wird loop
in die globale Microtask-Warteschlange verschoben, da es sich um eine Funktion aus dem äußeren (Haupt-)Kontext handelt und somit auch das Timeout umgehen kann.
Wenn asynchrone Planungsfunktionen wie process.nextTick()
, queueMicrotask()
, setTimeout()
, setImmediate()
usw. innerhalb eines vm.Context
verfügbar gemacht werden, werden Funktionen, die an sie übergeben werden, globalen Warteschlangen hinzugefügt, die von allen Kontexten gemeinsam genutzt werden. Daher sind Callbacks, die an diese Funktionen übergeben werden, auch nicht durch das Timeout steuerbar.
Unterstützung von dynamischem import()
in Kompilierungs-APIs
Die folgenden APIs unterstützen eine importModuleDynamically
-Option, um dynamisches import()
im Code zu aktivieren, der vom VM-Modul kompiliert wird.
new vm.Script
vm.compileFunction()
new vm.SourceTextModule
vm.runInThisContext()
vm.runInContext()
vm.runInNewContext()
vm.createContext()
Diese Option ist weiterhin Teil der experimentellen Module-API. Wir empfehlen, sie nicht in einer Produktionsumgebung zu verwenden.
Wenn die Option importModuleDynamically
nicht angegeben oder undefiniert ist
Wenn diese Option nicht angegeben ist oder wenn sie undefined
ist, kann Code, der import()
enthält, weiterhin von den VM-APIs kompiliert werden. Wenn der kompilierte Code jedoch ausgeführt wird und tatsächlich import()
aufruft, wird das Ergebnis mit ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING
abgelehnt.
Wenn importModuleDynamically
vm.constants.USE_MAIN_CONTEXT_DEFAULT_LOADER
ist
Diese Option wird derzeit für vm.SourceTextModule
nicht unterstützt.
Mit dieser Option verwendet Node.js beim Initiieren eines import()
im kompilierten Code den Standard-ESM-Loader aus dem Hauptkontext, um das angeforderte Modul zu laden und an den Code zurückzugeben, der ausgeführt wird.
Dies ermöglicht dem zu kompilierenden Code den Zugriff auf in Node.js integrierte Module wie fs
oder http
. Wenn der Code in einem anderen Kontext ausgeführt wird, beachten Sie, dass die von Modulen erstellten Objekte, die aus dem Hauptkontext geladen werden, weiterhin aus dem Hauptkontext stammen und nicht instanceof
in den integrierten Klassen im neuen Kontext sind.
const { Script, constants } = require('node:vm');
const script = new Script(
'import("node:fs").then(({readFile}) => readFile instanceof Function)',
{ importModuleDynamically: constants.USE_MAIN_CONTEXT_DEFAULT_LOADER });
// false: Die aus dem Hauptkontext geladene URL ist keine Instanz der Function-Klasse
// im neuen Kontext.
script.runInNewContext().then(console.log);
import { Script, constants } from 'node:vm';
const script = new Script(
'import("node:fs").then(({readFile}) => readFile instanceof Function)',
{ importModuleDynamically: constants.USE_MAIN_CONTEXT_DEFAULT_LOADER });
// false: Die aus dem Hauptkontext geladene URL ist keine Instanz der Function-Klasse
// im neuen Kontext.
script.runInNewContext().then(console.log);
Diese Option ermöglicht es dem Skript oder der Funktion auch, Benutzermodule zu laden:
import { Script, constants } from 'node:vm';
import { resolve } from 'node:path';
import { writeFileSync } from 'node:fs';
// Schreibe test.js und test.txt in das Verzeichnis, in dem sich das aktuelle Skript
// befindet, das gerade ausgeführt wird.
writeFileSync(resolve(import.meta.dirname, 'test.mjs'),
'export const filename = "./test.json";');
writeFileSync(resolve(import.meta.dirname, 'test.json'),
'{"hello": "world"}');
// Kompiliere ein Skript, das test.mjs und dann test.json lädt
// so, als ob sich das Skript im selben Verzeichnis befindet.
const script = new Script(
`(async function() {
const { filename } = await import('./test.mjs');
return import(filename, { with: { type: 'json' } })
})();`,
{
filename: resolve(import.meta.dirname, 'test-with-default.js'),
importModuleDynamically: constants.USE_MAIN_CONTEXT_DEFAULT_LOADER,
});
// { default: { hello: 'world' } }
script.runInThisContext().then(console.log);
const { Script, constants } = require('node:vm');
const { resolve } = require('node:path');
const { writeFileSync } = require('node:fs');
// Schreibe test.js und test.txt in das Verzeichnis, in dem sich das aktuelle Skript
// befindet, das gerade ausgeführt wird.
writeFileSync(resolve(__dirname, 'test.mjs'),
'export const filename = "./test.json";');
writeFileSync(resolve(__dirname, 'test.json'),
'{"hello": "world"}');
// Kompiliere ein Skript, das test.mjs und dann test.json lädt
// so, als ob sich das Skript im selben Verzeichnis befindet.
const script = new Script(
`(async function() {
const { filename } = await import('./test.mjs');
return import(filename, { with: { type: 'json' } })
})();`,
{
filename: resolve(__dirname, 'test-with-default.js'),
importModuleDynamically: constants.USE_MAIN_CONTEXT_DEFAULT_LOADER,
});
// { default: { hello: 'world' } }
script.runInThisContext().then(console.log);
Es gibt ein paar Einschränkungen beim Laden von Benutzermodulen mithilfe des Standardladers aus dem Hauptkontext:
Wenn importModuleDynamically
eine Funktion ist
Wenn importModuleDynamically
eine Funktion ist, wird sie aufgerufen, wenn import()
im kompilierten Code aufgerufen wird, damit Benutzer anpassen können, wie das angeforderte Modul kompiliert und ausgewertet werden soll. Derzeit muss die Node.js-Instanz mit dem Flag --experimental-vm-modules
gestartet werden, damit diese Option funktioniert. Wenn das Flag nicht gesetzt ist, wird dieser Callback ignoriert. Wenn der ausgewertete Code tatsächlich import()
aufruft, wird das Ergebnis mit ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING_FLAG
abgelehnt.
Der Callback importModuleDynamically(specifier, referrer, importAttributes)
hat die folgende Signatur:
specifier
<string> Animport()
übergebener Bezeichnerreferrer
<vm.Script> | <Function> | <vm.SourceTextModule> | <Object> Der Referrer ist das kompiliertevm.Script
fürnew vm.Script
,vm.runInThisContext
,vm.runInContext
undvm.runInNewContext
. Es ist die kompilierteFunction
fürvm.compileFunction
, das kompiliertevm.SourceTextModule
fürnew vm.SourceTextModule
und das KontextObject
fürvm.createContext()
.importAttributes
<Object> Der"with"
-Wert, der an den optionalen ParameteroptionsExpression
übergeben wurde, oder ein leeres Objekt, wenn kein Wert angegeben wurde.- Gibt zurück: <Modul-Namensraum-Objekt> | <vm.Module> Die Rückgabe eines
vm.Module
wird empfohlen, um die Fehlernachverfolgung zu nutzen und Probleme mit Namensräumen zu vermeiden, diethen
-Funktionsexporte enthalten.
// Dieses Skript muss mit --experimental-vm-modules ausgeführt werden.
import { Script, SyntheticModule } from 'node:vm';
const script = new Script('import("foo.json", { with: { type: "json" } })', {
async importModuleDynamically(specifier, referrer, importAttributes) {
console.log(specifier); // 'foo.json'
console.log(referrer); // Das kompilierte Skript
console.log(importAttributes); // { type: 'json' }
const m = new SyntheticModule(['bar'], () => { });
await m.link(() => { });
m.setExport('bar', { hello: 'world' });
return m;
},
});
const result = await script.runInThisContext();
console.log(result); // { bar: { hello: 'world' } }
// Dieses Skript muss mit --experimental-vm-modules ausgeführt werden.
const { Script, SyntheticModule } = require('node:vm');
(async function main() {
const script = new Script('import("foo.json", { with: { type: "json" } })', {
async importModuleDynamically(specifier, referrer, importAttributes) {
console.log(specifier); // 'foo.json'
console.log(referrer); // Das kompilierte Skript
console.log(importAttributes); // { type: 'json' }
const m = new SyntheticModule(['bar'], () => { });
await m.link(() => { });
m.setExport('bar', { hello: 'world' });
return m;
},
});
const result = await script.runInThisContext();
console.log(result); // { bar: { hello: 'world' } }
})();