@@ -408,7 +408,78 @@ This implementation lies at a lower level than the [ECMAScript Module
408408loader] [ ] . There is also no way to interact with the Loader yet, though
409409support is planned.
410410
411- ``` js
411+ ``` mjs
412+ import vm from ' vm' ;
413+
414+ const contextifiedObject = vm .createContext ({
415+ secret: 42 ,
416+ print: console .log ,
417+ });
418+
419+ // Step 1
420+ //
421+ // Create a Module by constructing a new `vm.SourceTextModule` object. This
422+ // parses the provided source text, throwing a `SyntaxError` if anything goes
423+ // wrong. By default, a Module is created in the top context. But here, we
424+ // specify `contextifiedObject` as the context this Module belongs to.
425+ //
426+ // Here, we attempt to obtain the default export from the module "foo", and
427+ // put it into local binding "secret".
428+
429+ const bar = new vm.SourceTextModule (`
430+ import s from 'foo';
431+ s;
432+ print(s);
433+ ` , { context: contextifiedObject });
434+
435+ // Step 2
436+ //
437+ // "Link" the imported dependencies of this Module to it.
438+ //
439+ // The provided linking callback (the "linker") accepts two arguments: the
440+ // parent module (`bar` in this case) and the string that is the specifier of
441+ // the imported module. The callback is expected to return a Module that
442+ // corresponds to the provided specifier, with certain requirements documented
443+ // in `module.link()`.
444+ //
445+ // If linking has not started for the returned Module, the same linker
446+ // callback will be called on the returned Module.
447+ //
448+ // Even top-level Modules without dependencies must be explicitly linked. The
449+ // callback provided would never be called, however.
450+ //
451+ // The link() method returns a Promise that will be resolved when all the
452+ // Promises returned by the linker resolve.
453+ //
454+ // Note: This is a contrived example in that the linker function creates a new
455+ // "foo" module every time it is called. In a full-fledged module system, a
456+ // cache would probably be used to avoid duplicated modules.
457+
458+ async function linker (specifier , referencingModule ) {
459+ if (specifier === ' foo' ) {
460+ return new vm.SourceTextModule (`
461+ // The "secret" variable refers to the global variable we added to
462+ // "contextifiedObject" when creating the context.
463+ export default secret;
464+ ` , { context: referencingModule .context });
465+
466+ // Using `contextifiedObject` instead of `referencingModule.context`
467+ // here would work as well.
468+ }
469+ throw new Error (` Unable to resolve dependency: ${ specifier} ` );
470+ }
471+ await bar .link (linker);
472+
473+ // Step 3
474+ //
475+ // Evaluate the Module. The evaluate() method returns a promise which will
476+ // resolve after the module has finished evaluating.
477+
478+ // Prints 42.
479+ await bar .evaluate ();
480+ ```
481+
482+ ``` cjs
412483const vm = require (' vm' );
413484
414485const contextifiedObject = vm .createContext ({
@@ -542,8 +613,7 @@ The identifier of the current module, as set in the constructor.
542613
543614* ` linker ` {Function}
544615 * ` specifier ` {string} The specifier of the requested module:
545- <!-- eslint-skip -->
546- ``` js
616+ ``` mjs
547617 import foo from ' foo' ;
548618 // ^^^^^ the module specifier
549619 ```
@@ -673,11 +743,37 @@ Properties assigned to the `import.meta` object that are objects may
673743allow the module to access information outside the specified `context`. Use
674744`vm.runInContext()` to create objects in a specific context.
675745
676- ```js
677- const vm = require( ' vm' ) ;
746+ ```mjs
747+ import vm from ' vm' ;
678748
679749const contextifiedObject = vm.createContext({ secret: 42 });
680750
751+ const module = new vm.SourceTextModule(
752+ ' Object .getPrototypeOf (import .meta.prop).secret = secret;' ,
753+ {
754+ initializeImportMeta(meta) {
755+ // Note: this object is created in the top context. As such,
756+ // Object.getPrototypeOf(import.meta.prop) points to the
757+ // Object.prototype in the top context rather than that in
758+ // the contextified object.
759+ meta.prop = {};
760+ }
761+ });
762+ // Since module has no dependencies, the linker function will never be called.
763+ await module.link(() => {});
764+ await module.evaluate();
765+
766+ // Now, Object.prototype.secret will be equal to 42.
767+ //
768+ // To fix this problem, replace
769+ // meta.prop = {};
770+ // above with
771+ // meta.prop = vm.runInContext(' {}' , contextifiedObject);
772+ ```
773+
774+ ```cjs
775+ const vm = require(' vm' );
776+ const contextifiedObject = vm.createContext({ secret: 42 });
681777(async () => {
682778 const module = new vm.SourceTextModule(
683779 ' Object .getPrototypeOf (import .meta.prop).secret = secret;' ,
@@ -693,7 +789,6 @@ const contextifiedObject = vm.createContext({ secret: 42 });
693789 // Since module has no dependencies, the linker function will never be called.
694790 await module.link(() => {});
695791 await module.evaluate();
696-
697792 // Now, Object.prototype.secret will be equal to 42.
698793 //
699794 // To fix this problem, replace
@@ -792,17 +887,27 @@ This method is used after the module is linked to set the values of exports. If
792887it is called before the module is linked, an [` ERR_VM_MODULE_STATUS` ][] error
793888will be thrown.
794889
795- ` ` ` js
796- const vm = require( 'vm') ;
890+ ` ` ` mjs
891+ import vm from 'vm';
797892
893+ const m = new vm.SyntheticModule(['x'], () => {
894+ m.setExport('x', 1);
895+ });
896+
897+ await m.link(() => {});
898+ await m.evaluate();
899+
900+ assert.strictEqual(m.namespace.x, 1);
901+ ` ` `
902+
903+ ` ` ` cjs
904+ const vm = require('vm');
798905(async () => {
799906 const m = new vm.SyntheticModule(['x'], () => {
800907 m.setExport('x', 1);
801908 });
802-
803909 await m.link(() => {});
804910 await m.evaluate();
805-
806911 assert.strictEqual(m.namespace.x, 1);
807912})();
808913` ` `
0 commit comments