| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -408,7 +408,78 @@ This implementation lies at a lower level than the [ECMAScript Module | |||
| 408 | 408 | loader][]. There is also no way to interact with the Loader yet, though | |
| 409 | 409 | support is planned. | |
| 410 | 410 | ||
| 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 | ||
| 412 | 483 | const vm = require('vm'); | |
| 413 | 484 | ||
| 414 | 485 | const contextifiedObject = vm.createContext({ | |
@@ -542,8 +613,7 @@ The identifier of the current module, as set in the constructor. | |||
| 542 | 613 | ||
| 543 | 614 | * `linker` {Function} | |
| 544 | 615 | * `specifier` {string} The specifier of the requested module: | |
| 545 | - <!-- eslint-skip --> | ||
| 546 | - ```js | ||
| 616 | + ```mjs | ||
| 547 | 617 | import foo from 'foo'; | |
| 548 | 618 | // ^^^^^ the module specifier | |
| 549 | 619 | ``` | |
@@ -673,11 +743,37 @@ Properties assigned to the `import.meta` object that are objects may | |||
| 673 | 743 | allow the module to access information outside the specified `context`. Use | |
| 674 | 744 | `vm.runInContext()` to create objects in a specific context. | |
| 675 | 745 | ||
| 676 | - ```js | ||
| 677 | - const vm = require('vm'); | ||
| 746 | + ```mjs | ||
| 747 | + import vm from 'vm'; | ||
| 678 | 748 | ||
| 679 | 749 | const contextifiedObject = vm.createContext({ secret: 42 }); | |
| 680 | 750 | ||
| 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 }); | ||
| 681 | 777 | (async () => { | |
| 682 | 778 | const module = new vm.SourceTextModule( | |
| 683 | 779 | 'Object.getPrototypeOf(import.meta.prop).secret = secret;', | |
@@ -693,7 +789,6 @@ const contextifiedObject = vm.createContext({ secret: 42 }); | |||
| 693 | 789 | // Since module has no dependencies, the linker function will never be called. | |
| 694 | 790 | await module.link(() => {}); | |
| 695 | 791 | await module.evaluate(); | |
| 696 | - | ||
| 697 | 792 | // Now, Object.prototype.secret will be equal to 42. | |
| 698 | 793 | // | |
| 699 | 794 | // 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 | |||
| 794 | 889 | it is called before the module is linked, an [`ERR_VM_MODULE_STATUS`][] error | |
| 795 | 890 | will be thrown. | |
| 796 | 891 | ||
| 797 | - ```js | ||
| 798 | - const vm = require('vm'); | ||
| 892 | + ```mjs | ||
| 893 | + import vm from 'vm'; | ||
| 799 | 894 | ||
| 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'); | ||
| 800 | 907 | (async () => { | |
| 801 | 908 | const m = new vm.SyntheticModule(['x'], () => { | |
| 802 | 909 | m.setExport('x', 1); | |
| 803 | 910 | }); | |
| 804 | - | ||
| 805 | 911 | await m.link(() => {}); | |
| 806 | 912 | await m.evaluate(); | |
| 807 | - | ||
| 808 | 913 | assert.strictEqual(m.namespace.x, 1); | |
| 809 | 914 | })(); | |
| 810 | 915 | ``` | |
| Back | FazBrowse Home | New Git URL |
0 commit comments