@@ -65,7 +65,8 @@ const WEBPACK_VERSION = Number.parseInt(
6565 * @import Parser, {
6666 * Range,
6767 * Members,
68- * DestructuringAssignmentProperty
68+ * DestructuringAssignmentProperty,
69+ * JavascriptParserState
6970 * } from "../../javascript/JavascriptParser"
7071 */
7172/** @import { RawRuntimeRequirements } from "../core/NullDependency" */
@@ -191,6 +192,12 @@ const importMetaVarName = (parser) => {
191192 return `__webpack_import_meta_${ index } __` ;
192193} ;
193194
195+ /**
196+ * The binding of each parse's synthesized `import.meta`, so it is set up once per module.
197+ * @type {WeakMap<JavascriptParserState, string> }
198+ */
199+ const importMetaObjects = new WeakMap ( ) ;
200+
194201/**
195202 * Checks whether the callee is the `import.meta.resolve` member.
196203 * @param {Expression | Super } callee call callee
@@ -407,12 +414,86 @@ class ImportMetaPlugin {
407414 JSON . stringify ( getUrl ( parser . state . module ) ) ;
408415 const importMetaWebpackVersion = ( ) =>
409416 JSON . stringify ( WEBPACK_VERSION ) ;
417+ /**
418+ * Initializes the module's shared import.meta object on demand.
419+ * @param {Expression } expression expression using the object
420+ * @returns {string } the object's local binding
421+ */
422+ const getImportMetaObject = ( expression ) => {
423+ const existing = importMetaObjects . get ( parser . state ) ;
424+ if ( existing !== undefined ) return existing ;
425+ const varName = importMetaVarName ( parser ) ;
426+ const knownProps = [ ] ;
427+ if ( isImportMetaFieldEnabled ( importMeta , "url" ) ) {
428+ knownProps . push ( `url: ${ importMetaUrl ( ) } ` ) ;
429+ }
430+ if ( isImportMetaFieldEnabled ( importMeta , "webpack" ) ) {
431+ knownProps . push ( `webpack: ${ importMetaWebpackVersion ( ) } ` ) ;
432+ }
433+ if ( isImportMetaFieldEnabled ( importMeta , "main" ) ) {
434+ knownProps . push ( `main: ${ renderImportMetaMain ( parser , false ) } ` ) ;
435+ }
436+ if ( isImportMetaFieldEnabled ( importMeta , "env" ) ) {
437+ addDefinitionValueDependencies ( ) ;
438+ knownProps . push (
439+ `env: ${ renderDefinition ( envNode , IMPORT_META_ENV ) } `
440+ ) ;
441+ }
442+ for ( const [ prop , node ] of customProps ) {
443+ addDefinitionValueDependencies ( ) ;
444+ knownProps . push (
445+ `${ DefinePlugin . toPropertyKey ( prop ) } : ${ renderDefinition (
446+ node ,
447+ `${ IMPORT_META } .${ prop } `
448+ ) } `
449+ ) ;
450+ }
451+ const plainInitCode = `var ${ varName } = {${ knownProps . join (
452+ ", "
453+ ) } };\n`;
454+ // Each module owns its `import.meta`: it copies the bundle's one
455+ // and inherits from it, so later host writes stay visible.
456+ const initCode = preserveUnknown ( importMeta )
457+ ? `var ${ varName } = Object.assign(Object.create(import.meta), import.meta, {${ knownProps . join (
458+ ", "
459+ ) } });\n`
460+ : plainInitCode ;
461+ /** @type {RawRuntimeRequirements } */
462+ const initRuntimeRequirements = [
463+ RuntimeGlobals . moduleCache ,
464+ RuntimeGlobals . entryModuleId ,
465+ RuntimeGlobals . module
466+ ] ;
467+ const initCodeRequirements =
468+ DefinePlugin . getRuntimeRequirements ( initCode ) ;
469+ if ( initCodeRequirements ) {
470+ initRuntimeRequirements . push ( ...initCodeRequirements ) ;
471+ }
472+ const initDep = new ModuleInitFragmentDependency (
473+ initCode ,
474+ initRuntimeRequirements ,
475+ varName ,
476+ // native `import.meta` does not parse in the build-time vm
477+ initCode === plainInitCode ? undefined : plainInitCode
478+ ) ;
479+ initDep . loc = parser . getLocation ( expression ) ;
480+ parser . state . module . addPresentationalDependency ( initDep ) ;
481+ importMetaObjects . set ( parser . state , varName ) ;
482+ return varName ;
483+ } ;
410484 /**
411485 * Import meta unknown property.
412486 * @param {Members } members members
413- * @returns {string } error message
487+ * @param {Expression } expression expression using the property
488+ * @returns {string } property access
414489 */
415- const importMetaUnknownProperty = ( members ) => {
490+ const importMetaUnknownProperty = ( members , expression ) => {
491+ if (
492+ preserveUnknown ( importMeta ) &&
493+ ! IMPORT_META_FIELDS . has ( members [ 0 ] )
494+ ) {
495+ return `${ getImportMetaObject ( expression ) } ${ propertyAccess ( members , 0 ) } ` ;
496+ }
416497 if (
417498 preserveUnknown ( importMeta ) ||
418499 ( IMPORT_META_FIELDS . has ( members [ 0 ] ) &&
@@ -426,12 +507,11 @@ class ImportMetaPlugin {
426507 } ;
427508 /**
428509 * @param {string } field field name
510+ * @param {Expression } expression expression using the property
429511 * @returns {string } generated property
430512 */
431- const importMetaRuntimeProperty = ( field ) =>
432- `[${ JSON . stringify ( field ) } ]: ${ importMetaUnknownProperty ( [
433- field
434- ] ) } ,`;
513+ const importMetaRuntimeProperty = ( field , expression ) =>
514+ `[${ JSON . stringify ( field ) } ]: ${ importMetaUnknownProperty ( [ field ] , expression ) } ,` ;
435515 /**
436516 * Import meta runtime property for build-time execution.
437517 * @param {string } field field name
@@ -472,64 +552,7 @@ class ImportMetaPlugin {
472552 const referencedPropertiesInDestructuring =
473553 parser . destructuringAssignmentPropertiesFor ( metaProperty ) ;
474554 if ( ! referencedPropertiesInDestructuring ) {
475- const varName = importMetaVarName ( parser ) ;
476- const knownProps = [ ] ;
477- if ( isImportMetaFieldEnabled ( importMeta , "url" ) ) {
478- knownProps . push ( `url: ${ importMetaUrl ( ) } ` ) ;
479- }
480- if ( isImportMetaFieldEnabled ( importMeta , "webpack" ) ) {
481- knownProps . push ( `webpack: ${ importMetaWebpackVersion ( ) } ` ) ;
482- }
483- if ( isImportMetaFieldEnabled ( importMeta , "main" ) ) {
484- knownProps . push (
485- `main: ${ renderImportMetaMain ( parser , false ) } `
486- ) ;
487- }
488- if ( isImportMetaFieldEnabled ( importMeta , "env" ) ) {
489- addDefinitionValueDependencies ( ) ;
490- knownProps . push (
491- `env: ${ renderDefinition ( envNode , IMPORT_META_ENV ) } `
492- ) ;
493- }
494- for ( const [ prop , node ] of customProps ) {
495- addDefinitionValueDependencies ( ) ;
496- knownProps . push (
497- `${ DefinePlugin . toPropertyKey ( prop ) } : ${ renderDefinition (
498- node ,
499- `${ IMPORT_META } .${ prop } `
500- ) } `
501- ) ;
502- }
503- const plainInitCode = `var ${ varName } = {${ knownProps . join (
504- ", "
505- ) } };\n`;
506- // Each module owns its `import.meta`: it copies the bundle's one
507- // and inherits from it, so later host writes stay visible.
508- const initCode = preserveUnknown ( importMeta )
509- ? `var ${ varName } = Object.assign(Object.create(import.meta), import.meta, {${ knownProps . join (
510- ", "
511- ) } });\n`
512- : plainInitCode ;
513- /** @type {RawRuntimeRequirements } */
514- const initRuntimeRequirements = [
515- RuntimeGlobals . moduleCache ,
516- RuntimeGlobals . entryModuleId ,
517- RuntimeGlobals . module
518- ] ;
519- const initCodeRequirements =
520- DefinePlugin . getRuntimeRequirements ( initCode ) ;
521- if ( initCodeRequirements ) {
522- initRuntimeRequirements . push ( ...initCodeRequirements ) ;
523- }
524- const initDep = new ModuleInitFragmentDependency (
525- initCode ,
526- initRuntimeRequirements ,
527- varName ,
528- // native `import.meta` does not parse in the build-time vm
529- initCode === plainInitCode ? undefined : plainInitCode
530- ) ;
531- initDep . loc = parser . getLocation ( metaProperty ) ;
532- parser . state . module . addPresentationalDependency ( initDep ) ;
555+ const varName = getImportMetaObject ( metaProperty ) ;
533556 const dep = new ConstDependency (
534557 varName ,
535558 /** @type {Range } */ ( metaProperty . range ) ,
@@ -551,12 +574,11 @@ class ImportMetaPlugin {
551574 strBuildTime += code ;
552575 } ;
553576 /**
554- * Appends a property reading native `import.meta`, which
555- * does not parse in the build-time vm.
577+ * Appends a runtime property with its build-time fallback.
556578 * @param {string } field field name
557579 */
558580 const appendRuntimeProperty = ( field ) => {
559- str += importMetaRuntimeProperty ( field ) ;
581+ str += importMetaRuntimeProperty ( field , metaProperty ) ;
560582 strBuildTime += importMetaBuildTimeProperty ( field ) ;
561583 } ;
562584 for ( const prop of referencedPropertiesInDestructuring ) {
@@ -882,10 +904,9 @@ class ImportMetaPlugin {
882904 ( IMPORT_META_FIELDS . has ( members [ 0 ] ) &&
883905 ! isImportMetaFieldEnabled ( importMeta , members [ 0 ] ) )
884906 ) {
885- // keep the native access verbatim for emitted output, but
886- // native `import.meta` does not parse in the build-time vm
907+ // Runtime properties are unavailable in the build-time vm.
887908 const dep = new BuildTimeConstDependency (
888- ` ${ IMPORT_META } ${ propertyAccess ( members , 0 ) } ` ,
909+ importMetaUnknownProperty ( members , expr ) ,
889910 `${ Template . toNormalComment (
890911 `unsupported import.meta.${ members . join ( "." ) } `
891912 ) } undefined${ propertyAccess ( members , 1 ) } `,
@@ -896,7 +917,7 @@ class ImportMetaPlugin {
896917 return true ;
897918 }
898919 const dep = new ConstDependency (
899- importMetaUnknownProperty ( members ) ,
920+ importMetaUnknownProperty ( members , expr ) ,
900921 /** @type {Range } */ ( expr . range )
901922 ) ;
902923 dep . loc = parser . getLocation ( expr ) ;
0 commit comments