@@ -151,6 +151,7 @@ function NativeModule(id) {
151151 this . id = id ;
152152 this . exports = { } ;
153153 this . reflect = undefined ;
154+ this . esmFacade = undefined ;
154155 this . exportKeys = undefined ;
155156 this . loaded = false ;
156157 this . loading = false ;
@@ -211,15 +212,19 @@ function requireWithFallbackInDeps(request) {
211212}
212213
213214// This is exposed for public loaders
214- NativeModule . prototype . compileForPublicLoader = function ( needToProxify ) {
215+ NativeModule . prototype . compileForPublicLoader = function ( needToSyncExports ) {
215216 if ( ! this . canBeRequiredByUsers ) {
216217 // No code because this is an assertion against bugs
217218 // eslint-disable-next-line no-restricted-syntax
218219 throw new Error ( `Should not compile ${ this . id } for public use` ) ;
219220 }
220221 this . compile ( ) ;
221- if ( needToProxify && ! this . exportKeys ) {
222- this . proxifyExports ( ) ;
222+ if ( needToSyncExports ) {
223+ if ( ! this . exportKeys ) {
224+ this . exportKeys = Object . keys ( this . exports ) ;
225+ }
226+ this . getESMFacade ( ) ;
227+ this . syncExports ( ) ;
223228 }
224229 return this . exports ;
225230} ;
@@ -230,61 +235,38 @@ const getOwn = (target, property, receiver) => {
230235 undefined ;
231236} ;
232237
238+ NativeModule . prototype . getURL = function ( ) {
239+ return `node:${ this . id } ` ;
240+ } ;
241+
242+ NativeModule . prototype . getESMFacade = function ( ) {
243+ if ( this . esmFacade ) return this . esmFacade ;
244+ const createDynamicModule = nativeModuleRequire (
245+ 'internal/modules/esm/create_dynamic_module' ) ;
246+ const url = this . getURL ( ) ;
247+ return this . esmFacade = createDynamicModule (
248+ [ ] , [ ...this . exportKeys , 'default' ] , url , ( reflect ) => {
249+ this . reflect = reflect ;
250+ this . syncExports ( ) ;
251+ reflect . exports . default . set ( this . exports ) ;
252+ } ) ;
253+ } ;
254+
233255// Provide named exports for all builtin libraries so that the libraries
234256// may be imported in a nicer way for ESM users. The default export is left
235- // as the entire namespace (module.exports) and wrapped in a proxy such
236- // that APMs and other behavior are still left intact.
237- NativeModule . prototype . proxifyExports = function ( ) {
238- this . exportKeys = Object . keys ( this . exports ) ;
239-
240- const update = ( property , value ) => {
241- if ( this . reflect !== undefined &&
242- ObjectPrototype . hasOwnProperty ( this . reflect . exports , property ) )
243- this . reflect . exports [ property ] . set ( value ) ;
244- } ;
245-
246- const handler = {
247- __proto__ : null ,
248- defineProperty : ( target , prop , descriptor ) => {
249- // Use `Object.defineProperty` instead of `Reflect.defineProperty`
250- // to throw the appropriate error if something goes wrong.
251- Object . defineProperty ( target , prop , descriptor ) ;
252- if ( typeof descriptor . get === 'function' &&
253- ! Reflect . has ( handler , 'get' ) ) {
254- handler . get = ( target , prop , receiver ) => {
255- const value = Reflect . get ( target , prop , receiver ) ;
256- if ( ObjectPrototype . hasOwnProperty ( target , prop ) )
257- update ( prop , value ) ;
258- return value ;
259- } ;
260- }
261- update ( prop , getOwn ( target , prop ) ) ;
262- return true ;
263- } ,
264- deleteProperty : ( target , prop ) => {
265- if ( Reflect . deleteProperty ( target , prop ) ) {
266- update ( prop , undefined ) ;
267- return true ;
268- }
269- return false ;
270- } ,
271- set : ( target , prop , value , receiver ) => {
272- const descriptor = Reflect . getOwnPropertyDescriptor ( target , prop ) ;
273- if ( Reflect . set ( target , prop , value , receiver ) ) {
274- if ( descriptor && typeof descriptor . set === 'function' ) {
275- for ( const key of this . exportKeys ) {
276- update ( key , getOwn ( target , key , receiver ) ) ;
277- }
278- } else {
279- update ( prop , getOwn ( target , prop , receiver ) ) ;
280- }
281- return true ;
282- }
283- return false ;
257+ // as the entire namespace (module.exports) and updates when this function is
258+ // called so that APMs and other behavior are supported.
259+ NativeModule . prototype . syncExports = function ( ) {
260+ const names = this . exportKeys ;
261+ if ( this . reflect ) {
262+ for ( let i = 0 ; i < names . length ; i ++ ) {
263+ const exportName = names [ i ] ;
264+ if ( exportName === 'default' ) continue ;
265+ this . reflect . exports [ exportName ] . set (
266+ getOwn ( this . exports , exportName , this . exports )
267+ ) ;
284268 }
285- } ;
286-
287- this . exports = new Proxy ( this . exports , handler ) ;
269+ }
288270} ;
289271
290272NativeModule . prototype . compile = function ( ) {
0 commit comments