From 4fbdb0e98b7f4404ec0499c656b8caad84ec9e7b Mon Sep 17 00:00:00 2001 From: yellowbeee <709341218@qq.com> Date: Thu, 6 Aug 2026 11:44:09 +0800 Subject: [PATCH 1/3] fix: copy guarded require properties safely --- .../implementation/guardedRequire.ts | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/packages/repack/src/plugins/RepackTargetPlugin/implementation/guardedRequire.ts b/packages/repack/src/plugins/RepackTargetPlugin/implementation/guardedRequire.ts index dd7834586..00a05cebe 100644 --- a/packages/repack/src/plugins/RepackTargetPlugin/implementation/guardedRequire.ts +++ b/packages/repack/src/plugins/RepackTargetPlugin/implementation/guardedRequire.ts @@ -27,10 +27,29 @@ module.exports = function () { } } - // Copy all properties from the original function to the wrapped function + // Copy the original require's runtime properties without invoking getters. + // Function intrinsics such as `prototype`, `arguments`, and `caller` are + // non-configurable on the wrapper and cannot be redefined. Assigning every + // property directly is also unsafe in strict-mode bundles because some + // function properties are read-only and would throw during startup. Object.getOwnPropertyNames(originalWebpackRequire).forEach((key) => { - // @ts-ignore - guardedWebpackRequire[key] = originalWebpackRequire[key]; + const sourceDescriptor = Object.getOwnPropertyDescriptor( + originalWebpackRequire, + key + ); + const targetDescriptor = Object.getOwnPropertyDescriptor( + guardedWebpackRequire, + key + ); + + if ( + !sourceDescriptor || + (targetDescriptor && !targetDescriptor.configurable) + ) { + return; + } + + Object.defineProperty(guardedWebpackRequire, key, sourceDescriptor); }); // @ts-ignore From 3f0933db93335de6d03b2214d2fab68204ad837e Mon Sep 17 00:00:00 2001 From: yellowbeee <709341218@qq.com> Date: Thu, 6 Aug 2026 11:45:33 +0800 Subject: [PATCH 2/3] test: cover guarded require strict mode --- .../__tests__/guardedRequire.test.ts | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 packages/repack/src/plugins/RepackTargetPlugin/implementation/__tests__/guardedRequire.test.ts diff --git a/packages/repack/src/plugins/RepackTargetPlugin/implementation/__tests__/guardedRequire.test.ts b/packages/repack/src/plugins/RepackTargetPlugin/implementation/__tests__/guardedRequire.test.ts new file mode 100644 index 000000000..f73dc9ee7 --- /dev/null +++ b/packages/repack/src/plugins/RepackTargetPlugin/implementation/__tests__/guardedRequire.test.ts @@ -0,0 +1,44 @@ +import vm from 'node:vm'; + +const guardedRequireImplementation = require('../guardedRequire'); + +describe('guardedRequire implementation', () => { + it('preserves runtime properties in strict mode', () => { + // Reproduce the strict wrapper emitted when an Rspack runtime is built as + // ESM. The previous direct assignments threw while copying Function + // intrinsics before React Native could execute the application entry. + const result = vm.runInNewContext(` + (function () { + 'use strict'; + var self = {}; + var factories = { page: function () { return 'page'; } }; + var __webpack_require__ = function originalWebpackRequire(moduleId) { + return moduleId; + }; + Object.defineProperty(__webpack_require__, 'm', { + configurable: true, + enumerable: false, + get: function () { return factories; } + }); + __webpack_require__.federation = { name: 'remote' }; + + (${guardedRequireImplementation + .toString() + .replaceAll('$globalObject$', 'self')})(); + + return { + value: __webpack_require__('page'), + factories: __webpack_require__.m, + federation: __webpack_require__.federation, + descriptor: Object.getOwnPropertyDescriptor(__webpack_require__, 'm') + }; + })() + `); + + expect(result.value).toBe('page'); + expect(result.factories.page()).toBe('page'); + expect(result.federation.name).toBe('remote'); + expect(result.descriptor.enumerable).toBe(false); + expect(typeof result.descriptor.get).toBe('function'); + }); +}); From 94c8ac81c76155f4fce6ec38ecf60762684b7670 Mon Sep 17 00:00:00 2001 From: yellowbeee <709341218@qq.com> Date: Thu, 6 Aug 2026 11:47:09 +0800 Subject: [PATCH 3/3] chore: add guarded require changeset --- .changeset/calm-cats-guard.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/calm-cats-guard.md diff --git a/.changeset/calm-cats-guard.md b/.changeset/calm-cats-guard.md new file mode 100644 index 000000000..6e749b024 --- /dev/null +++ b/.changeset/calm-cats-guard.md @@ -0,0 +1,5 @@ +--- +'@callstack/repack': patch +--- + +Prevent guarded require initialization from throwing in strict-mode bundles by safely copying runtime property descriptors.