Skip to content

Commit 77b3699

Browse files
authored
feat: add polyfills (#3)
1 parent 1ac4624 commit 77b3699

14 files changed

Lines changed: 400 additions & 7 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ android/keystores/debug.keystore
7878
# generated by bob
7979
lib/
8080

81+
# Polyfills build output
82+
packages/polyfills/dist/
83+
8184
# React Native Codegen
8285
ios/generated
8386
android/generated

cpp/Polyfills.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Auto-generated file - DO NOT EDIT
2+
// Generated by: packages/polyfills/scripts/generate-header.js
3+
4+
#pragma once
5+
6+
namespace webworker {
7+
8+
constexpr const char* kPolyfillScript = R"POLYFILL(
9+
var __BUNDLE_START_TIME__=globalThis.nativePerformanceNow?nativePerformanceNow():Date.now(),__DEV__=false,process=globalThis.process||{},__METRO_GLOBAL_PREFIX__='';process.env=process.env||{};process.env.NODE_ENV=process.env.NODE_ENV||"production";
10+
!(function(e){"use strict";e.__r=i,e[`${__METRO_GLOBAL_PREFIX__}__d`]=function(e,o,n){if(r.has(o))return;var i={dependencyMap:n,factory:e,hasError:!1,importedAll:t,importedDefault:t,isInitialized:!1,publicModule:{exports:{}}};r.set(o,i)},e.__c=n,e.__registerSegment=function(e,t,o){s[e]=t,o&&o.forEach(t=>{r.has(t)||v.has(t)||v.set(t,e)})};var r=n(),t={},o={}.hasOwnProperty;function n(){return r=new Map}function i(e,t){if(null===e)throw new Error("Cannot find module");var o=e,n=r.get(o);return n&&n.isInitialized?n.publicModule.exports:d(o,n)}function a(e){var o=e,n=r.get(o);if(n&&n.importedDefault!==t)return n.importedDefault;var a=i(o),l=a&&a.__esModule?a.default:a;return r.get(o).importedDefault=l}function l(e){var n=e,a=r.get(n);if(a&&a.importedAll!==t)return a.importedAll;var l,u=i(n);if(u&&u.__esModule)l=u;else{if(l={},u)for(var d in u)o.call(u,d)&&(l[d]=u[d]);l.default=u}return r.get(n).importedAll=l}i.importDefault=a,i.importAll=l,i.context=function(){throw new Error("The experimental Metro feature `require.context` is not enabled in your project.")},i.resolveWeak=function(){throw new Error("require.resolveWeak cannot be called dynamically.")};var u=!1;function d(r,t){if(!u&&e.ErrorUtils){var o;u=!0;try{o=h(r,t)}catch(r){e.ErrorUtils.reportFatalError(r)}return u=!1,o}return h(r,t)}var f=16,c=65535;function p(e){return{segmentId:e>>>f,localId:e&c}}i.unpackModuleId=p,i.packModuleId=function(e){return(e.segmentId<<f)+e.localId};var s=[],v=new Map;function h(t,o){if(!o&&s.length>0){var n=v.get(t)??0,u=s[n];null!=u&&(u(t),o=r.get(t),v.delete(t))}var d=e.nativeRequire;if(!o&&d){var f=p(t),c=f.segmentId;d(f.localId,c),o=r.get(t)}if(!o)throw Error('Requiring unknown module "'+t+'".');if(o.hasError)throw o.error;o.isInitialized=!0;var h=o,g=h.factory,m=h.dependencyMap;try{var _=o.publicModule;return _.id=t,g(e,i,a,l,_,_.exports,m),o.factory=void 0,o.dependencyMap=void 0,_.exports}catch(e){throw o.hasError=!0,o.error=e,o.isInitialized=!1,o.publicModule.exports=void 0,e}}})('undefined'!=typeof globalThis?globalThis:'undefined'!=typeof global?global:'undefined'!=typeof window?window:this);
11+
__d(function(g,r,i,a,m,e,d){r(d[0])},0,[1]);
12+
__d(function(_g,r,i,a,m,e,d){"use strict";var o=r(d[0]),n="undefined"!=typeof self?self:"undefined"!=typeof window?window:void 0!==_g?_g:void 0;n&&(void 0===n.AbortController&&(n.AbortController=o.AbortController),void 0===n.AbortSignal&&(n.AbortSignal=o.AbortSignal))},1,[2]);
13+
__d(function(g,r,i,a,m,_e,d){'use strict';var t=r(d[0]),e=t(r(d[1])),o=t(r(d[2])),n=t(r(d[3])),l=t(r(d[4])),u=t(r(d[5]));function c(){try{var t=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(t){}return(c=function(){return!!t})()}Object.defineProperty(_e,'__esModule',{value:!0});var f=r(d[6]),b=(function(t){function f(){var t,o,u;throw(0,e.default)(this,f),t=this,o=f,o=(0,l.default)(o),(0,n.default)(t,c()?Reflect.construct(o,u||[],(0,l.default)(t).constructor):o.apply(t,u)),new TypeError("AbortSignal cannot be constructed directly")}return(0,u.default)(f,t),(0,o.default)(f,[{key:"aborted",get:function(){var t=p.get(this);if("boolean"!=typeof t)throw new TypeError("Expected 'this' to be an 'AbortSignal' object, but got "+(null===this?"null":typeof this));return t}}])})(f.EventTarget);f.defineEventAttribute(b.prototype,"abort");var p=new WeakMap;Object.defineProperties(b.prototype,{aborted:{enumerable:!0}}),"function"==typeof Symbol&&"symbol"==typeof Symbol.toStringTag&&Object.defineProperty(b.prototype,Symbol.toStringTag,{configurable:!0,value:"AbortSignal"});var y=(function(){return(0,o.default)(function t(){var o;(0,e.default)(this,t),s.set(this,(o=Object.create(b.prototype),f.EventTarget.call(o),p.set(o,!1),o))},[{key:"signal",get:function(){return v(this)}},{key:"abort",value:function(){var t;t=v(this),!1===p.get(t)&&(p.set(t,!0),t.dispatchEvent({type:"abort"}))}}])})(),s=new WeakMap;function v(t){var e=s.get(t);if(null==e)throw new TypeError("Expected 'this' to be an 'AbortController' object, but got "+(null===t?"null":typeof t));return e}Object.defineProperties(y.prototype,{signal:{enumerable:!0},abort:{enumerable:!0}}),"function"==typeof Symbol&&"symbol"==typeof Symbol.toStringTag&&Object.defineProperty(y.prototype,Symbol.toStringTag,{configurable:!0,value:"AbortController"}),_e.AbortController=y,_e.AbortSignal=b,_e.default=y,m.exports=y,m.exports.AbortController=m.exports.default=y,m.exports.AbortSignal=b},2,[3,4,5,9,11,12,14]);
14+
__d(function(g,r,i,a,m,_e,d){m.exports=function(e){return e&&e.__esModule?e:{default:e}},m.exports.__esModule=!0,m.exports.default=m.exports},3,[]);
15+
__d(function(g,r,i,_a,m,e,d){m.exports=function(o,n){if(!(o instanceof n))throw new TypeError("Cannot call a class as a function")},m.exports.__esModule=!0,m.exports.default=m.exports},4,[]);
16+
__d(function(g,_r,i,a,m,_e,d){var e=_r(d[0]);function r(r,t){for(var o=0;o<t.length;o++){var n=t[o];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(r,e(n.key),n)}}m.exports=function(e,t,o){return t&&r(e.prototype,t),o&&r(e,o),Object.defineProperty(e,"prototype",{writable:!1}),e},m.exports.__esModule=!0,m.exports.default=m.exports},5,[6]);
17+
__d(function(g,r,_i,a,m,e,d){var t=r(d[0]).default,o=r(d[1]);m.exports=function(s){var n=o(s,"string");return"symbol"==t(n)?n:n+""},m.exports.__esModule=!0,m.exports.default=m.exports},6,[7,8]);
18+
__d(function(g,r,i,a,m,e,d){function o(t){return m.exports=o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(o){return typeof o}:function(o){return o&&"function"==typeof Symbol&&o.constructor===Symbol&&o!==Symbol.prototype?"symbol":typeof o},m.exports.__esModule=!0,m.exports.default=m.exports,o(t)}m.exports=o,m.exports.__esModule=!0,m.exports.default=m.exports},7,[]);
19+
__d(function(g,_r,_i,a,m,_e,d){var r=_r(d[0]).default;m.exports=function(t,e){if("object"!=r(t)||!t)return t;var i=t[Symbol.toPrimitive];if(void 0!==i){var o=i.call(t,e||"default");if("object"!=r(o))return o;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===e?String:Number)(t)},m.exports.__esModule=!0,m.exports.default=m.exports},8,[7]);
20+
__d(function(g,r,i,a,m,_e,d){var e=r(d[0]).default,o=r(d[1]);m.exports=function(t,n){if(n&&("object"==e(n)||"function"==typeof n))return n;if(void 0!==n)throw new TypeError("Derived constructors may only return object or undefined");return o(t)},m.exports.__esModule=!0,m.exports.default=m.exports},9,[7,10]);
21+
__d(function(g,r,i,a,m,_e,d){m.exports=function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e},m.exports.__esModule=!0,m.exports.default=m.exports},10,[]);
22+
__d(function(g,r,i,a,m,e,d){function t(o){return m.exports=t=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(t){return t.__proto__||Object.getPrototypeOf(t)},m.exports.__esModule=!0,m.exports.default=m.exports,t(o)}m.exports=t,m.exports.__esModule=!0,m.exports.default=m.exports},11,[]);
23+
__d(function(g,r,i,a,m,_e,d){var e=r(d[0]);m.exports=function(t,o){if("function"!=typeof o&&null!==o)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(o&&o.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),Object.defineProperty(t,"prototype",{writable:!1}),o&&e(t,o)},m.exports.__esModule=!0,m.exports.default=m.exports},12,[13]);
24+
__d(function(g,r,i,a,m,_e,d){function t(e,o){return m.exports=t=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(t,e){return t.__proto__=e,t},m.exports.__esModule=!0,m.exports.default=m.exports,t(e,o)}m.exports=t,m.exports.__esModule=!0,m.exports.default=m.exports},13,[]);
25+
__d(function(g,r,_i,a,m,e,d){
26+
/**
27+
* @author Toru Nagashima <https://github.com/mysticatea>
28+
* @copyright 2015 Toru Nagashima. All rights reserved.
29+
* See LICENSE file in root directory for full license.
30+
*/
31+
'use strict';Object.defineProperty(e,'__esModule',{value:!0});var t=new WeakMap,n=new WeakMap;function o(n){var o=t.get(n);return console.assert(null!=o,"'this' is expected an Event object, but got",n),o}function i(t){null==t.passiveListener?t.event.cancelable&&(t.canceled=!0,"function"==typeof t.event.preventDefault&&t.event.preventDefault()):"undefined"!=typeof console&&"function"==typeof console.error&&console.error("Unable to preventDefault inside passive event listener invocation.",t.passiveListener)}function l(n,o){t.set(this,{eventTarget:n,event:o,eventPhase:2,currentTarget:n,canceled:!1,stopped:!1,immediateStopped:!1,passiveListener:null,timeStamp:o.timeStamp||Date.now()}),Object.defineProperty(this,"isTrusted",{value:!1,enumerable:!0});for(var i=Object.keys(o),l=0;l<i.length;++l){var s=i[l];s in this||Object.defineProperty(this,s,u(s))}}function u(t){return{get(){return o(this).event[t]},set(n){o(this).event[t]=n},configurable:!0,enumerable:!0}}function s(t){return{value(){var n=o(this).event;return n[t].apply(n,arguments)},configurable:!0,enumerable:!0}}function p(t,n){var o=Object.keys(n);if(0===o.length)return t;function i(n,o){t.call(this,n,o)}i.prototype=Object.create(t.prototype,{constructor:{value:i,configurable:!0,writable:!0}});for(var l=0;l<o.length;++l){var p=o[l];if(!(p in t.prototype)){var c="function"==typeof Object.getOwnPropertyDescriptor(n,p).value;Object.defineProperty(i.prototype,p,c?s(p):u(p))}}return i}function c(t){if(null==t||t===Object.prototype)return l;var o=n.get(t);return null==o&&(o=p(c(Object.getPrototypeOf(t)),t),n.set(t,o)),o}function f(t,n){return new(c(Object.getPrototypeOf(n)))(t,n)}function v(t){return o(t).immediateStopped}function y(t,n){o(t).eventPhase=n}function b(t,n){o(t).currentTarget=n}function h(t,n){o(t).passiveListener=n}l.prototype={get type(){return o(this).event.type},get target(){return o(this).eventTarget},get currentTarget(){return o(this).currentTarget},composedPath(){var t=o(this).currentTarget;return null==t?[]:[t]},get NONE(){return 0},get CAPTURING_PHASE(){return 1},get AT_TARGET(){return 2},get BUBBLING_PHASE(){return 3},get eventPhase(){return o(this).eventPhase},stopPropagation(){var t=o(this);t.stopped=!0,"function"==typeof t.event.stopPropagation&&t.event.stopPropagation()},stopImmediatePropagation(){var t=o(this);t.stopped=!0,t.immediateStopped=!0,"function"==typeof t.event.stopImmediatePropagation&&t.event.stopImmediatePropagation()},get bubbles(){return Boolean(o(this).event.bubbles)},get cancelable(){return Boolean(o(this).event.cancelable)},preventDefault(){i(o(this))},get defaultPrevented(){return o(this).canceled},get composed(){return Boolean(o(this).event.composed)},get timeStamp(){return o(this).timeStamp},get srcElement(){return o(this).eventTarget},get cancelBubble(){return o(this).stopped},set cancelBubble(t){if(t){var n=o(this);n.stopped=!0,"boolean"==typeof n.event.cancelBubble&&(n.event.cancelBubble=!0)}},get returnValue(){return!o(this).canceled},set returnValue(t){t||i(o(this))},initEvent(){}},Object.defineProperty(l.prototype,"constructor",{value:l,configurable:!0,writable:!0}),"undefined"!=typeof window&&void 0!==window.Event&&(Object.setPrototypeOf(l.prototype,window.Event.prototype),n.set(window.Event.prototype,l));var w=new WeakMap;function T(t){return null!==t&&"object"==typeof t}function P(t){var n=w.get(t);if(null==n)throw new TypeError("'this' is expected an EventTarget object, but got another value.");return n}function x(t){return{get(){for(var n=P(this).get(t);null!=n;){if(3===n.listenerType)return n.listener;n=n.next}return null},set(n){"function"==typeof n||T(n)||(n=null);for(var o=P(this),i=null,l=o.get(t);null!=l;)3===l.listenerType?null!==i?i.next=l.next:null!==l.next?o.set(t,l.next):o.delete(t):i=l,l=l.next;if(null!==n){var u={listener:n,listenerType:3,passive:!1,once:!1,next:null};null===i?o.set(t,u):i.next=u}},configurable:!0,enumerable:!0}}function E(t,n){Object.defineProperty(t,`on${n}`,x(n))}function O(t){function n(){j.call(this)}n.prototype=Object.create(j.prototype,{constructor:{value:n,configurable:!0,writable:!0}});for(var o=0;o<t.length;++o)E(n.prototype,t[o]);return n}function j(){if(!(this instanceof j)){if(1===arguments.length&&Array.isArray(arguments[0]))return O(arguments[0]);if(arguments.length>0){for(var t=new Array(arguments.length),n=0;n<arguments.length;++n)t[n]=arguments[n];return O(t)}throw new TypeError("Cannot call a class as a function")}w.set(this,new Map)}j.prototype={addEventListener(t,n,o){if(null!=n){if("function"!=typeof n&&!T(n))throw new TypeError("'listener' should be a function or an object.");var i=P(this),l=T(o),u=(l?Boolean(o.capture):Boolean(o))?1:2,s={listener:n,listenerType:u,passive:l&&Boolean(o.passive),once:l&&Boolean(o.once),next:null},p=i.get(t);if(void 0!==p){for(var c=null;null!=p;){if(p.listener===n&&p.listenerType===u)return;c=p,p=p.next}c.next=s}else i.set(t,s)}},removeEventListener(t,n,o){if(null!=n)for(var i=P(this),l=(T(o)?Boolean(o.capture):Boolean(o))?1:2,u=null,s=i.get(t);null!=s;){if(s.listener===n&&s.listenerType===l)return void(null!==u?u.next=s.next:null!==s.next?i.set(t,s.next):i.delete(t));u=s,s=s.next}},dispatchEvent(t){if(null==t||"string"!=typeof t.type)throw new TypeError('"event.type" should be a string.');var n=P(this),o=t.type,i=n.get(o);if(null==i)return!0;for(var l=f(this,t),u=null;null!=i;){if(i.once?null!==u?u.next=i.next:null!==i.next?n.set(o,i.next):n.delete(o):u=i,h(l,i.passive?i.listener:null),"function"==typeof i.listener)try{i.listener.call(this,l)}catch(t){"undefined"!=typeof console&&"function"==typeof console.error&&console.error(t)}else 3!==i.listenerType&&"function"==typeof i.listener.handleEvent&&i.listener.handleEvent(l);if(v(l))break;i=i.next}return h(l,null),y(l,0),b(l,null),!l.defaultPrevented}},Object.defineProperty(j.prototype,"constructor",{value:j,configurable:!0,writable:!0}),"undefined"!=typeof window&&void 0!==window.EventTarget&&Object.setPrototypeOf(j.prototype,window.EventTarget.prototype),e.defineEventAttribute=E,e.EventTarget=j,e.default=j,m.exports=j,m.exports.EventTarget=m.exports.default=j,m.exports.defineEventAttribute=E},14,[]);
32+
__r(0);
33+
)POLYFILL";
34+
35+
} // namespace webworker

cpp/WebWorkerCore.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "WebWorkerCore.h"
2+
#include "Polyfills.h"
23
#include "networking/ResponseHostObject.h"
34
#include <iostream>
45
#include <sstream>
@@ -304,6 +305,12 @@ void WorkerRuntime::setupGlobalScope() {
304305
try {
305306
Runtime& runtime = *hermesRuntime_;
306307

308+
// Execute polyfills first (TextEncoder, URL, AbortController, etc.)
309+
runtime.evaluateJavaScript(
310+
std::make_shared<StringBuffer>(kPolyfillScript),
311+
"polyfills.js"
312+
);
313+
307314
std::string initScript = R"(
308315
var self = this;
309316
var global = this;

docs/POLYFILLS.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Polyfills in web workers
2+
3+
The `react-native-webworker` library includes built-in polyfills to provide essential web APIs that are missing from Hermes. Every worker automatically gets these polyfills loaded before your code runs.
4+
5+
## What it does
6+
7+
Every worker comes with polyfills for APIs that Hermes doesn't implement but that web developers expect. Behind the scenes, it uses proven polyfill libraries to provide:
8+
9+
- **AbortController** - Cancel asynchronous operations
10+
- *(Room for future polyfills)*
11+
12+
This ensures your worker code can use modern JavaScript APIs without worrying about Hermes compatibility.
13+
14+
## Adding new polyfills
15+
16+
You can easily extend the polyfill bundle by adding new APIs:
17+
18+
### Adding a polyfill
19+
20+
1. Install the polyfill package:
21+
22+
```bash
23+
cd packages/polyfills
24+
yarn add text-encoding-polyfill
25+
```
26+
27+
2. Import it in the source file:
28+
29+
```javascript
30+
// packages/polyfills/src/index.js
31+
import 'abort-controller/polyfill';
32+
import 'text-encoding-polyfill'; // New polyfill
33+
```
34+
35+
3. Rebuild the polyfills:
36+
37+
```bash
38+
cd packages/polyfills
39+
yarn build
40+
```
41+
42+
The new polyfill will be automatically available in all workers.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { afterEach, describe, it, expect } from 'react-native-harness';
2+
import { Worker } from 'react-native-webworker';
3+
4+
// Helper to prevent tests from hanging indefinitely
5+
function withTimeout<T>(
6+
promise: Promise<T>,
7+
ms: number = 2000,
8+
msg: string = 'Operation timed out'
9+
): Promise<T> {
10+
return Promise.race([
11+
promise,
12+
new Promise<T>((_, reject) => setTimeout(() => reject(new Error(msg)), ms)),
13+
]);
14+
}
15+
16+
describe('Polyfills', () => {
17+
let worker: Worker;
18+
19+
afterEach(() => {
20+
worker.terminate();
21+
});
22+
23+
it('should add AbortController to the global object', async () => {
24+
worker = new Worker({
25+
script: `
26+
self.onmessage = function(event) {
27+
self.postMessage(typeof AbortController);
28+
};
29+
`,
30+
name: 'test-worker',
31+
});
32+
33+
const responsePromise = new Promise<string>((resolve, reject) => {
34+
worker.onmessage = (event) => {
35+
resolve(event.data as string);
36+
};
37+
worker.onerror = (err) => {
38+
reject(err);
39+
};
40+
});
41+
42+
await worker.postMessage('start');
43+
44+
const result = await withTimeout(
45+
responsePromise,
46+
2000,
47+
'Worker did not respond with AbortController type'
48+
);
49+
50+
expect(result).toBe('function');
51+
});
52+
});

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@
9191
"react-native": "*"
9292
},
9393
"workspaces": [
94-
"example"
94+
"example",
95+
"packages/*"
9596
],
9697
"packageManager": "yarn@4.11.0",
9798
"react-native-builder-bob": {

packages/polyfills/babel.config.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
module.exports = {
2+
presets: [
3+
[
4+
'@react-native/babel-preset',
5+
{
6+
// Use hermes-stable profile to ensure all incompatible constructs are transformed
7+
unstable_transformProfile: 'hermes-stable',
8+
},
9+
],
10+
],
11+
};

packages/polyfills/metro.config.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const path = require('path');
2+
3+
module.exports = {
4+
// Project configuration
5+
projectRoot: __dirname,
6+
watchFolders: [__dirname],
7+
8+
// Resolver configuration
9+
resolver: {
10+
sourceExts: ['js', 'mjs', 'cjs', 'json'],
11+
nodeModulesPaths: [path.join(__dirname, 'node_modules')],
12+
},
13+
};

packages/polyfills/package.json

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"name": "@react-native-webworker/polyfills",
3+
"description": "Polyfills for React Native WebWorker",
4+
"version": "0.1.0",
5+
"private": true,
6+
"scripts": {
7+
"build": "node scripts/build.js && node scripts/generate-header.js"
8+
},
9+
"devDependencies": {
10+
"@babel/core": "^7.20.0",
11+
"@react-native/babel-preset": "^0.83.0",
12+
"metro": "^0.83.0",
13+
"metro-babel-transformer": "^0.83.0",
14+
"metro-minify-terser": "^0.83.0",
15+
"metro-resolver": "^0.83.0",
16+
"abort-controller": "3.0.0"
17+
},
18+
"repository": {
19+
"type": "git",
20+
"url": "git+https://github.com/V3RON/react-native-webworker.git"
21+
},
22+
"author": "Szymon Chmal <szymon@chmal.it> (https://github.com/V3RON)",
23+
"license": "MIT",
24+
"bugs": {
25+
"url": "https://github.com/V3RON/react-native-webworker/issues"
26+
},
27+
"homepage": "https://github.com/V3RON/react-native-webworker#readme",
28+
"publishConfig": {
29+
"registry": "https://registry.npmjs.org/"
30+
}
31+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
const Metro = require('metro');
2+
const path = require('path');
3+
const fs = require('fs');
4+
5+
async function build() {
6+
const projectRoot = path.join(__dirname, '..');
7+
const distDir = path.join(projectRoot, 'dist');
8+
9+
if (!fs.existsSync(distDir)) {
10+
fs.mkdirSync(distDir, { recursive: true });
11+
}
12+
13+
const config = await Metro.loadConfig({
14+
config: path.join(projectRoot, 'metro.config.js'),
15+
});
16+
17+
await Metro.runBuild(config, {
18+
entry: path.join(projectRoot, 'src/index.js'),
19+
out: path.join(distDir, 'polyfills.bundle.js'),
20+
platform: 'ios',
21+
minify: true,
22+
dev: false,
23+
});
24+
25+
console.log('Bundle created: dist/polyfills.bundle.js');
26+
}
27+
28+
build().catch((error) => {
29+
console.error('Build failed:', error);
30+
process.exit(1);
31+
});

0 commit comments

Comments
 (0)