node-internal-modules-cjs-helpers.js 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. // Copied from https://github.com/nodejs/node/blob/v17.0.1/lib/internal/modules/cjs/helpers.js
  2. 'use strict';
  3. const {
  4. ArrayPrototypeForEach,
  5. ObjectDefineProperty,
  6. ObjectPrototypeHasOwnProperty,
  7. SafeSet,
  8. StringPrototypeIncludes,
  9. StringPrototypeStartsWith,
  10. } = require('./node-primordials');
  11. const { getOptionValue } = require('./node-options');
  12. const userConditions = getOptionValue('--conditions');
  13. const noAddons = getOptionValue('--no-addons');
  14. const addonConditions = noAddons ? [] : ['node-addons'];
  15. // TODO: Use this set when resolving pkg#exports conditions in loader.js.
  16. const cjsConditions = new SafeSet([
  17. 'require',
  18. 'node',
  19. ...addonConditions,
  20. ...userConditions,
  21. ]);
  22. /**
  23. * @param {any} object
  24. * @param {string} [dummyModuleName]
  25. * @return {void}
  26. */
  27. function addBuiltinLibsToObject(object, dummyModuleName) {
  28. // Make built-in modules available directly (loaded lazily).
  29. const Module = require('module').Module;
  30. const { builtinModules } = Module;
  31. // To require built-in modules in user-land and ignore modules whose
  32. // `canBeRequiredByUsers` is false. So we create a dummy module object and not
  33. // use `require()` directly.
  34. const dummyModule = new Module(dummyModuleName);
  35. ArrayPrototypeForEach(builtinModules, (name) => {
  36. // Neither add underscored modules, nor ones that contain slashes (e.g.,
  37. // 'fs/promises') or ones that are already defined.
  38. if (StringPrototypeStartsWith(name, '_') ||
  39. StringPrototypeIncludes(name, '/') ||
  40. ObjectPrototypeHasOwnProperty(object, name)) {
  41. return;
  42. }
  43. // Goals of this mechanism are:
  44. // - Lazy loading of built-in modules
  45. // - Having all built-in modules available as non-enumerable properties
  46. // - Allowing the user to re-assign these variables as if there were no
  47. // pre-existing globals with the same name.
  48. const setReal = (val) => {
  49. // Deleting the property before re-assigning it disables the
  50. // getter/setter mechanism.
  51. delete object[name];
  52. object[name] = val;
  53. };
  54. ObjectDefineProperty(object, name, {
  55. get: () => {
  56. // Node 12 hack; remove when we drop node12 support
  57. const lib = (dummyModule.require || require)(name);
  58. // Disable the current getter/setter and set up a new
  59. // non-enumerable property.
  60. delete object[name];
  61. ObjectDefineProperty(object, name, {
  62. get: () => lib,
  63. set: setReal,
  64. configurable: true,
  65. enumerable: false
  66. });
  67. return lib;
  68. },
  69. set: setReal,
  70. configurable: true,
  71. enumerable: false
  72. });
  73. });
  74. }
  75. exports.addBuiltinLibsToObject = addBuiltinLibsToObject;
  76. exports.cjsConditions = cjsConditions;