diff options
author | Bradley Farias <bfarias@godaddy.com> | 2019-09-27 20:12:18 +0300 |
---|---|---|
committer | Guy Bedford <guybedford@gmail.com> | 2019-10-06 03:11:15 +0300 |
commit | 0b495a899bdf9a26b25a6e31177512531c841e0e (patch) | |
tree | d0c3a6b3768c0882ddf2eae1a01df419b50bb38f /lib/internal/bootstrap | |
parent | e1e2f669f65fd53323b8a58d80ed3cee039706b7 (diff) |
esm: remove proxy for builtin exports
PR-URL: https://github.com/nodejs/node/pull/29737
Reviewed-By: Guy Bedford <guybedford@gmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Jan Krems <jan.krems@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Minwoo Jung <minwoo@nodesource.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Diffstat (limited to 'lib/internal/bootstrap')
-rw-r--r-- | lib/internal/bootstrap/loaders.js | 92 |
1 files changed, 37 insertions, 55 deletions
diff --git a/lib/internal/bootstrap/loaders.js b/lib/internal/bootstrap/loaders.js index cc1157a5577..dbc21a9697e 100644 --- a/lib/internal/bootstrap/loaders.js +++ b/lib/internal/bootstrap/loaders.js @@ -151,6 +151,7 @@ function NativeModule(id) { this.id = id; this.exports = {}; this.reflect = undefined; + this.esmFacade = undefined; this.exportKeys = undefined; this.loaded = false; this.loading = false; @@ -211,15 +212,19 @@ function requireWithFallbackInDeps(request) { } // This is exposed for public loaders -NativeModule.prototype.compileForPublicLoader = function(needToProxify) { +NativeModule.prototype.compileForPublicLoader = function(needToSyncExports) { if (!this.canBeRequiredByUsers) { // No code because this is an assertion against bugs // eslint-disable-next-line no-restricted-syntax throw new Error(`Should not compile ${this.id} for public use`); } this.compile(); - if (needToProxify && !this.exportKeys) { - this.proxifyExports(); + if (needToSyncExports) { + if (!this.exportKeys) { + this.exportKeys = Object.keys(this.exports); + } + this.getESMFacade(); + this.syncExports(); } return this.exports; }; @@ -230,61 +235,38 @@ const getOwn = (target, property, receiver) => { undefined; }; +NativeModule.prototype.getURL = function() { + return `node:${this.id}`; +}; + +NativeModule.prototype.getESMFacade = function() { + if (this.esmFacade) return this.esmFacade; + const createDynamicModule = nativeModuleRequire( + 'internal/modules/esm/create_dynamic_module'); + const url = this.getURL(); + return this.esmFacade = createDynamicModule( + [], [...this.exportKeys, 'default'], url, (reflect) => { + this.reflect = reflect; + this.syncExports(); + reflect.exports.default.set(this.exports); + }); +}; + // Provide named exports for all builtin libraries so that the libraries // may be imported in a nicer way for ESM users. The default export is left -// as the entire namespace (module.exports) and wrapped in a proxy such -// that APMs and other behavior are still left intact. -NativeModule.prototype.proxifyExports = function() { - this.exportKeys = Object.keys(this.exports); - - const update = (property, value) => { - if (this.reflect !== undefined && - ObjectPrototype.hasOwnProperty(this.reflect.exports, property)) - this.reflect.exports[property].set(value); - }; - - const handler = { - __proto__: null, - defineProperty: (target, prop, descriptor) => { - // Use `Object.defineProperty` instead of `Reflect.defineProperty` - // to throw the appropriate error if something goes wrong. - Object.defineProperty(target, prop, descriptor); - if (typeof descriptor.get === 'function' && - !Reflect.has(handler, 'get')) { - handler.get = (target, prop, receiver) => { - const value = Reflect.get(target, prop, receiver); - if (ObjectPrototype.hasOwnProperty(target, prop)) - update(prop, value); - return value; - }; - } - update(prop, getOwn(target, prop)); - return true; - }, - deleteProperty: (target, prop) => { - if (Reflect.deleteProperty(target, prop)) { - update(prop, undefined); - return true; - } - return false; - }, - set: (target, prop, value, receiver) => { - const descriptor = Reflect.getOwnPropertyDescriptor(target, prop); - if (Reflect.set(target, prop, value, receiver)) { - if (descriptor && typeof descriptor.set === 'function') { - for (const key of this.exportKeys) { - update(key, getOwn(target, key, receiver)); - } - } else { - update(prop, getOwn(target, prop, receiver)); - } - return true; - } - return false; +// as the entire namespace (module.exports) and updates when this function is +// called so that APMs and other behavior are supported. +NativeModule.prototype.syncExports = function() { + const names = this.exportKeys; + if (this.reflect) { + for (let i = 0; i < names.length; i++) { + const exportName = names[i]; + if (exportName === 'default') continue; + this.reflect.exports[exportName].set( + getOwn(this.exports, exportName, this.exports) + ); } - }; - - this.exports = new Proxy(this.exports, handler); + } }; NativeModule.prototype.compile = function() { |