@@ -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
@@ -794,17 +889,27 @@ This method is used after the module is linked to set the values of exports. If
794889it is called before the module is linked, an [` ERR_VM_MODULE_STATUS` ][] error
795890will be thrown.
796891
797- ` ` ` js
798- const vm = require( 'vm') ;
892+ ` ` ` mjs
893+ import vm from 'vm';
799894
895+ const m = new vm.SyntheticModule(['x'], () => {
896+ m.setExport('x', 1);
897+ });
898+
899+ await m.link(() => {});
900+ await m.evaluate();
901+
902+ assert.strictEqual(m.namespace.x, 1);
903+ ` ` `
904+
905+ ` ` ` cjs
906+ const vm = require('vm');
800907(async () => {
801908 const m = new vm.SyntheticModule(['x'], () => {
802909 m.setExport('x', 1);
803910 });
804-
805911 await m.link(() => {});
806912 await m.evaluate();
807-
808913 assert.strictEqual(m.namespace.x, 1);
809914})();
810915` ` `
0 commit comments