@react-three/fiber 8.15.2 → 8.15.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @react-three/fiber
2
2
 
3
+ ## 8.15.4
4
+
5
+ ### Patch Changes
6
+
7
+ - 634e5db5: fix(native): harden Blob URI check for Android
8
+
9
+ ## 8.15.3
10
+
11
+ ### Patch Changes
12
+
13
+ - beab4344: fix(native): workaround Android content policy for Blob URI
14
+
3
15
  ## 8.15.2
4
16
 
5
17
  ### Patch Changes
@@ -282,110 +282,105 @@ const Canvas = /*#__PURE__*/React__namespace.forwardRef(function CanvasWrapper(p
282
282
  })));
283
283
  });
284
284
 
285
- function polyfills() {
286
- // http://stackoverflow.com/questions/105034
287
- function uuidv4() {
288
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
289
- const r = Math.random() * 16 | 0,
290
- v = c == 'x' ? r : r & 0x3 | 0x8;
291
- return v.toString(16);
292
- });
293
- }
285
+ // http://stackoverflow.com/questions/105034
286
+ function uuidv4() {
287
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
288
+ const r = Math.random() * 16 | 0,
289
+ v = c == 'x' ? r : r & 0x3 | 0x8;
290
+ return v.toString(16);
291
+ });
292
+ }
293
+ async function getAsset(input) {
294
+ if (typeof input === 'string') {
295
+ var _NativeModules$BlobMo;
296
+ // Don't process storage
297
+ if (input.startsWith('file:')) return input;
294
298
 
295
- // Patch Blob for ArrayBuffer if unsupported
296
- // https://github.com/facebook/react-native/pull/39276
297
- try {
298
- new Blob([new ArrayBuffer(4)]);
299
- } catch (_) {
300
- const BlobManager = require('react-native/Libraries/Blob/BlobManager.js');
301
- BlobManager.createFromParts = function createFromParts(parts, options) {
302
- const blobId = uuidv4();
303
- const items = parts.map(part => {
304
- if (part instanceof ArrayBuffer || ArrayBuffer.isView(part)) {
305
- const data = base64Js.fromByteArray(new Uint8Array(part));
306
- return {
307
- data,
308
- type: 'string'
309
- };
310
- } else if (part instanceof Blob) {
311
- return {
312
- data: part.data,
313
- type: 'blob'
314
- };
315
- } else {
316
- return {
317
- data: String(part),
318
- type: 'string'
319
- };
320
- }
299
+ // Unpack Blobs from react-native BlobManager
300
+ // https://github.com/facebook/react-native/issues/22681#issuecomment-523258955
301
+ if (input.startsWith('blob:') || input.startsWith((_NativeModules$BlobMo = reactNative.NativeModules.BlobModule) == null ? void 0 : _NativeModules$BlobMo.BLOB_URI_SCHEME)) {
302
+ const blob = await new Promise((res, rej) => {
303
+ const xhr = new XMLHttpRequest();
304
+ xhr.open('GET', input);
305
+ xhr.responseType = 'blob';
306
+ xhr.onload = () => res(xhr.response);
307
+ xhr.onerror = rej;
308
+ xhr.send();
321
309
  });
322
- const size = items.reduce((acc, curr) => {
323
- if (curr.type === 'string') {
324
- return acc + global.unescape(encodeURI(curr.data)).length;
325
- } else {
326
- return acc + curr.data.size;
327
- }
328
- }, 0);
329
- reactNative.NativeModules.BlobModule.createFromParts(items, blobId);
330
- return BlobManager.createFromOptions({
331
- blobId,
332
- offset: 0,
333
- size,
334
- type: options ? options.type : '',
335
- lastModified: options ? options.lastModified : Date.now()
310
+ const data = await new Promise((res, rej) => {
311
+ const reader = new FileReader();
312
+ reader.onload = () => res(reader.result);
313
+ reader.onerror = rej;
314
+ reader.readAsText(blob);
336
315
  });
337
- };
338
- }
339
- async function getAsset(input) {
340
- if (typeof input === 'string') {
341
- // Don't process storage
342
- if (input.startsWith('file:')) return input;
343
-
344
- // Unpack Blobs from react-native BlobManager
345
- if (input.startsWith('blob:')) {
346
- const blob = await new Promise((res, rej) => {
347
- const xhr = new XMLHttpRequest();
348
- xhr.open('GET', input);
349
- xhr.responseType = 'blob';
350
- xhr.onload = () => res(xhr.response);
351
- xhr.onerror = rej;
352
- xhr.send();
353
- });
354
- const data = await new Promise((res, rej) => {
355
- const reader = new FileReader();
356
- reader.onload = () => res(reader.result);
357
- reader.onerror = rej;
358
- reader.readAsText(blob);
359
- });
360
- input = `data:${blob.type};base64,${data}`;
361
- }
316
+ input = `data:${blob.type};base64,${data}`;
317
+ }
362
318
 
363
- // Create safe URI for JSI
364
- if (input.startsWith('data:')) {
365
- const [header, data] = input.split(';base64,');
366
- const [, type] = header.split('/');
367
- const uri = fs__namespace.cacheDirectory + uuidv4() + `.${type}`;
368
- await fs__namespace.writeAsStringAsync(uri, data, {
369
- encoding: fs__namespace.EncodingType.Base64
370
- });
371
- return uri;
372
- }
319
+ // Create safe URI for JSI serialization
320
+ if (input.startsWith('data:')) {
321
+ const [header, data] = input.split(';base64,');
322
+ const [, type] = header.split('/');
323
+ const uri = fs__namespace.cacheDirectory + uuidv4() + `.${type}`;
324
+ await fs__namespace.writeAsStringAsync(uri, data, {
325
+ encoding: fs__namespace.EncodingType.Base64
326
+ });
327
+ return uri;
373
328
  }
329
+ }
374
330
 
375
- // Download bundler module or external URL
376
- const asset = await expoAsset.Asset.fromModule(input).downloadAsync();
377
- let uri = asset.localUri || asset.uri;
331
+ // Download bundler module or external URL
332
+ const asset = await expoAsset.Asset.fromModule(input).downloadAsync();
333
+ let uri = asset.localUri || asset.uri;
378
334
 
379
- // Unpack assets in Android Release Mode
380
- if (!uri.includes(':')) {
381
- const file = `${fs__namespace.cacheDirectory}ExponentAsset-${asset.hash}.${asset.type}`;
382
- await fs__namespace.copyAsync({
383
- from: uri,
384
- to: file
385
- });
386
- uri = file;
335
+ // Unpack assets in Android Release Mode
336
+ if (!uri.includes(':')) {
337
+ const file = `${fs__namespace.cacheDirectory}ExponentAsset-${asset.hash}.${asset.type}`;
338
+ await fs__namespace.copyAsync({
339
+ from: uri,
340
+ to: file
341
+ });
342
+ uri = file;
343
+ }
344
+ return uri;
345
+ }
346
+ function polyfills() {
347
+ // Patch Blob for ArrayBuffer and URL if unsupported
348
+ // https://github.com/pmndrs/react-three-fiber/pull/3059
349
+ // https://github.com/pmndrs/react-three-fiber/issues/3058
350
+ if (reactNative.Platform.OS !== 'web') {
351
+ try {
352
+ const blob = new Blob([new ArrayBuffer(4)]);
353
+ const url = URL.createObjectURL(blob);
354
+ URL.revokeObjectURL(url);
355
+ } catch (_) {
356
+ const BlobManager = require('react-native/Libraries/Blob/BlobManager.js');
357
+ const createObjectURL = URL.createObjectURL;
358
+ URL.createObjectURL = function (blob) {
359
+ if (blob.data._base64) {
360
+ return `data:${blob.type};base64,${blob.data._base64}`;
361
+ }
362
+ return createObjectURL(blob);
363
+ };
364
+ const createFromParts = BlobManager.createFromParts;
365
+ BlobManager.createFromParts = function (parts, options) {
366
+ var _NativeModules$BlobMo2;
367
+ parts = parts.map(part => {
368
+ if (part instanceof ArrayBuffer || ArrayBuffer.isView(part)) {
369
+ part = base64Js.fromByteArray(new Uint8Array(part));
370
+ }
371
+ return part;
372
+ });
373
+ const blob = createFromParts(parts, options);
374
+ if (!((_NativeModules$BlobMo2 = reactNative.NativeModules.BlobModule) != null && _NativeModules$BlobMo2.BLOB_URI_SCHEME)) {
375
+ blob.data._base64 = '';
376
+ for (const part of parts) {
377
+ var _data$_base, _data;
378
+ blob.data._base64 += (_data$_base = (_data = part.data) == null ? void 0 : _data._base64) != null ? _data$_base : part;
379
+ }
380
+ }
381
+ return blob;
382
+ };
387
383
  }
388
- return uri;
389
384
  }
390
385
 
391
386
  // Don't pre-process urls, let expo-asset generate an absolute URL
@@ -395,7 +390,6 @@ function polyfills() {
395
390
  // There's no Image in native, so create a data texture instead
396
391
  THREE__namespace.TextureLoader.prototype.load = function load(url, onLoad, onProgress, onError) {
397
392
  if (this.path && typeof url === 'string') url = this.path + url;
398
- this.manager.itemStart(url);
399
393
  const texture = new THREE__namespace.Texture();
400
394
  getAsset(url).then(async uri => {
401
395
  // https://github.com/expo/expo-three/pull/266
@@ -421,12 +415,7 @@ function polyfills() {
421
415
  // @ts-ignore
422
416
  texture.isDataTexture = true;
423
417
  onLoad == null ? void 0 : onLoad(texture);
424
- }).catch(error => {
425
- onError == null ? void 0 : onError(error);
426
- this.manager.itemError(url);
427
- }).finally(() => {
428
- this.manager.itemEnd(url);
429
- });
418
+ }).catch(onError);
430
419
  return texture;
431
420
  };
432
421
 
@@ -282,110 +282,105 @@ const Canvas = /*#__PURE__*/React__namespace.forwardRef(function CanvasWrapper(p
282
282
  })));
283
283
  });
284
284
 
285
- function polyfills() {
286
- // http://stackoverflow.com/questions/105034
287
- function uuidv4() {
288
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
289
- const r = Math.random() * 16 | 0,
290
- v = c == 'x' ? r : r & 0x3 | 0x8;
291
- return v.toString(16);
292
- });
293
- }
285
+ // http://stackoverflow.com/questions/105034
286
+ function uuidv4() {
287
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
288
+ const r = Math.random() * 16 | 0,
289
+ v = c == 'x' ? r : r & 0x3 | 0x8;
290
+ return v.toString(16);
291
+ });
292
+ }
293
+ async function getAsset(input) {
294
+ if (typeof input === 'string') {
295
+ var _NativeModules$BlobMo;
296
+ // Don't process storage
297
+ if (input.startsWith('file:')) return input;
294
298
 
295
- // Patch Blob for ArrayBuffer if unsupported
296
- // https://github.com/facebook/react-native/pull/39276
297
- try {
298
- new Blob([new ArrayBuffer(4)]);
299
- } catch (_) {
300
- const BlobManager = require('react-native/Libraries/Blob/BlobManager.js');
301
- BlobManager.createFromParts = function createFromParts(parts, options) {
302
- const blobId = uuidv4();
303
- const items = parts.map(part => {
304
- if (part instanceof ArrayBuffer || ArrayBuffer.isView(part)) {
305
- const data = base64Js.fromByteArray(new Uint8Array(part));
306
- return {
307
- data,
308
- type: 'string'
309
- };
310
- } else if (part instanceof Blob) {
311
- return {
312
- data: part.data,
313
- type: 'blob'
314
- };
315
- } else {
316
- return {
317
- data: String(part),
318
- type: 'string'
319
- };
320
- }
299
+ // Unpack Blobs from react-native BlobManager
300
+ // https://github.com/facebook/react-native/issues/22681#issuecomment-523258955
301
+ if (input.startsWith('blob:') || input.startsWith((_NativeModules$BlobMo = reactNative.NativeModules.BlobModule) == null ? void 0 : _NativeModules$BlobMo.BLOB_URI_SCHEME)) {
302
+ const blob = await new Promise((res, rej) => {
303
+ const xhr = new XMLHttpRequest();
304
+ xhr.open('GET', input);
305
+ xhr.responseType = 'blob';
306
+ xhr.onload = () => res(xhr.response);
307
+ xhr.onerror = rej;
308
+ xhr.send();
321
309
  });
322
- const size = items.reduce((acc, curr) => {
323
- if (curr.type === 'string') {
324
- return acc + global.unescape(encodeURI(curr.data)).length;
325
- } else {
326
- return acc + curr.data.size;
327
- }
328
- }, 0);
329
- reactNative.NativeModules.BlobModule.createFromParts(items, blobId);
330
- return BlobManager.createFromOptions({
331
- blobId,
332
- offset: 0,
333
- size,
334
- type: options ? options.type : '',
335
- lastModified: options ? options.lastModified : Date.now()
310
+ const data = await new Promise((res, rej) => {
311
+ const reader = new FileReader();
312
+ reader.onload = () => res(reader.result);
313
+ reader.onerror = rej;
314
+ reader.readAsText(blob);
336
315
  });
337
- };
338
- }
339
- async function getAsset(input) {
340
- if (typeof input === 'string') {
341
- // Don't process storage
342
- if (input.startsWith('file:')) return input;
343
-
344
- // Unpack Blobs from react-native BlobManager
345
- if (input.startsWith('blob:')) {
346
- const blob = await new Promise((res, rej) => {
347
- const xhr = new XMLHttpRequest();
348
- xhr.open('GET', input);
349
- xhr.responseType = 'blob';
350
- xhr.onload = () => res(xhr.response);
351
- xhr.onerror = rej;
352
- xhr.send();
353
- });
354
- const data = await new Promise((res, rej) => {
355
- const reader = new FileReader();
356
- reader.onload = () => res(reader.result);
357
- reader.onerror = rej;
358
- reader.readAsText(blob);
359
- });
360
- input = `data:${blob.type};base64,${data}`;
361
- }
316
+ input = `data:${blob.type};base64,${data}`;
317
+ }
362
318
 
363
- // Create safe URI for JSI
364
- if (input.startsWith('data:')) {
365
- const [header, data] = input.split(';base64,');
366
- const [, type] = header.split('/');
367
- const uri = fs__namespace.cacheDirectory + uuidv4() + `.${type}`;
368
- await fs__namespace.writeAsStringAsync(uri, data, {
369
- encoding: fs__namespace.EncodingType.Base64
370
- });
371
- return uri;
372
- }
319
+ // Create safe URI for JSI serialization
320
+ if (input.startsWith('data:')) {
321
+ const [header, data] = input.split(';base64,');
322
+ const [, type] = header.split('/');
323
+ const uri = fs__namespace.cacheDirectory + uuidv4() + `.${type}`;
324
+ await fs__namespace.writeAsStringAsync(uri, data, {
325
+ encoding: fs__namespace.EncodingType.Base64
326
+ });
327
+ return uri;
373
328
  }
329
+ }
374
330
 
375
- // Download bundler module or external URL
376
- const asset = await expoAsset.Asset.fromModule(input).downloadAsync();
377
- let uri = asset.localUri || asset.uri;
331
+ // Download bundler module or external URL
332
+ const asset = await expoAsset.Asset.fromModule(input).downloadAsync();
333
+ let uri = asset.localUri || asset.uri;
378
334
 
379
- // Unpack assets in Android Release Mode
380
- if (!uri.includes(':')) {
381
- const file = `${fs__namespace.cacheDirectory}ExponentAsset-${asset.hash}.${asset.type}`;
382
- await fs__namespace.copyAsync({
383
- from: uri,
384
- to: file
385
- });
386
- uri = file;
335
+ // Unpack assets in Android Release Mode
336
+ if (!uri.includes(':')) {
337
+ const file = `${fs__namespace.cacheDirectory}ExponentAsset-${asset.hash}.${asset.type}`;
338
+ await fs__namespace.copyAsync({
339
+ from: uri,
340
+ to: file
341
+ });
342
+ uri = file;
343
+ }
344
+ return uri;
345
+ }
346
+ function polyfills() {
347
+ // Patch Blob for ArrayBuffer and URL if unsupported
348
+ // https://github.com/pmndrs/react-three-fiber/pull/3059
349
+ // https://github.com/pmndrs/react-three-fiber/issues/3058
350
+ if (reactNative.Platform.OS !== 'web') {
351
+ try {
352
+ const blob = new Blob([new ArrayBuffer(4)]);
353
+ const url = URL.createObjectURL(blob);
354
+ URL.revokeObjectURL(url);
355
+ } catch (_) {
356
+ const BlobManager = require('react-native/Libraries/Blob/BlobManager.js');
357
+ const createObjectURL = URL.createObjectURL;
358
+ URL.createObjectURL = function (blob) {
359
+ if (blob.data._base64) {
360
+ return `data:${blob.type};base64,${blob.data._base64}`;
361
+ }
362
+ return createObjectURL(blob);
363
+ };
364
+ const createFromParts = BlobManager.createFromParts;
365
+ BlobManager.createFromParts = function (parts, options) {
366
+ var _NativeModules$BlobMo2;
367
+ parts = parts.map(part => {
368
+ if (part instanceof ArrayBuffer || ArrayBuffer.isView(part)) {
369
+ part = base64Js.fromByteArray(new Uint8Array(part));
370
+ }
371
+ return part;
372
+ });
373
+ const blob = createFromParts(parts, options);
374
+ if (!((_NativeModules$BlobMo2 = reactNative.NativeModules.BlobModule) != null && _NativeModules$BlobMo2.BLOB_URI_SCHEME)) {
375
+ blob.data._base64 = '';
376
+ for (const part of parts) {
377
+ var _data$_base, _data;
378
+ blob.data._base64 += (_data$_base = (_data = part.data) == null ? void 0 : _data._base64) != null ? _data$_base : part;
379
+ }
380
+ }
381
+ return blob;
382
+ };
387
383
  }
388
- return uri;
389
384
  }
390
385
 
391
386
  // Don't pre-process urls, let expo-asset generate an absolute URL
@@ -395,7 +390,6 @@ function polyfills() {
395
390
  // There's no Image in native, so create a data texture instead
396
391
  THREE__namespace.TextureLoader.prototype.load = function load(url, onLoad, onProgress, onError) {
397
392
  if (this.path && typeof url === 'string') url = this.path + url;
398
- this.manager.itemStart(url);
399
393
  const texture = new THREE__namespace.Texture();
400
394
  getAsset(url).then(async uri => {
401
395
  // https://github.com/expo/expo-three/pull/266
@@ -421,12 +415,7 @@ function polyfills() {
421
415
  // @ts-ignore
422
416
  texture.isDataTexture = true;
423
417
  onLoad == null ? void 0 : onLoad(texture);
424
- }).catch(error => {
425
- onError == null ? void 0 : onError(error);
426
- this.manager.itemError(url);
427
- }).finally(() => {
428
- this.manager.itemEnd(url);
429
- });
418
+ }).catch(onError);
430
419
  return texture;
431
420
  };
432
421
 
@@ -3,7 +3,7 @@ export { t as ReactThreeFiber, x as _roots, v as act, o as addAfterEffect, n as
3
3
  import _extends from '@babel/runtime/helpers/esm/extends';
4
4
  import * as React from 'react';
5
5
  import * as THREE from 'three';
6
- import { PanResponder, PixelRatio, View, StyleSheet, NativeModules, Image, Platform } from 'react-native';
6
+ import { PanResponder, PixelRatio, View, StyleSheet, Platform, NativeModules, Image } from 'react-native';
7
7
  import { GLView } from 'expo-gl';
8
8
  import { FiberProvider, useContextBridge } from 'its-fine';
9
9
  import { Asset } from 'expo-asset';
@@ -257,110 +257,105 @@ const Canvas = /*#__PURE__*/React.forwardRef(function CanvasWrapper(props, ref)
257
257
  })));
258
258
  });
259
259
 
260
- function polyfills() {
261
- // http://stackoverflow.com/questions/105034
262
- function uuidv4() {
263
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
264
- const r = Math.random() * 16 | 0,
265
- v = c == 'x' ? r : r & 0x3 | 0x8;
266
- return v.toString(16);
267
- });
268
- }
260
+ // http://stackoverflow.com/questions/105034
261
+ function uuidv4() {
262
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
263
+ const r = Math.random() * 16 | 0,
264
+ v = c == 'x' ? r : r & 0x3 | 0x8;
265
+ return v.toString(16);
266
+ });
267
+ }
268
+ async function getAsset(input) {
269
+ if (typeof input === 'string') {
270
+ var _NativeModules$BlobMo;
271
+ // Don't process storage
272
+ if (input.startsWith('file:')) return input;
269
273
 
270
- // Patch Blob for ArrayBuffer if unsupported
271
- // https://github.com/facebook/react-native/pull/39276
272
- try {
273
- new Blob([new ArrayBuffer(4)]);
274
- } catch (_) {
275
- const BlobManager = require('react-native/Libraries/Blob/BlobManager.js');
276
- BlobManager.createFromParts = function createFromParts(parts, options) {
277
- const blobId = uuidv4();
278
- const items = parts.map(part => {
279
- if (part instanceof ArrayBuffer || ArrayBuffer.isView(part)) {
280
- const data = fromByteArray(new Uint8Array(part));
281
- return {
282
- data,
283
- type: 'string'
284
- };
285
- } else if (part instanceof Blob) {
286
- return {
287
- data: part.data,
288
- type: 'blob'
289
- };
290
- } else {
291
- return {
292
- data: String(part),
293
- type: 'string'
294
- };
295
- }
274
+ // Unpack Blobs from react-native BlobManager
275
+ // https://github.com/facebook/react-native/issues/22681#issuecomment-523258955
276
+ if (input.startsWith('blob:') || input.startsWith((_NativeModules$BlobMo = NativeModules.BlobModule) == null ? void 0 : _NativeModules$BlobMo.BLOB_URI_SCHEME)) {
277
+ const blob = await new Promise((res, rej) => {
278
+ const xhr = new XMLHttpRequest();
279
+ xhr.open('GET', input);
280
+ xhr.responseType = 'blob';
281
+ xhr.onload = () => res(xhr.response);
282
+ xhr.onerror = rej;
283
+ xhr.send();
296
284
  });
297
- const size = items.reduce((acc, curr) => {
298
- if (curr.type === 'string') {
299
- return acc + global.unescape(encodeURI(curr.data)).length;
300
- } else {
301
- return acc + curr.data.size;
302
- }
303
- }, 0);
304
- NativeModules.BlobModule.createFromParts(items, blobId);
305
- return BlobManager.createFromOptions({
306
- blobId,
307
- offset: 0,
308
- size,
309
- type: options ? options.type : '',
310
- lastModified: options ? options.lastModified : Date.now()
285
+ const data = await new Promise((res, rej) => {
286
+ const reader = new FileReader();
287
+ reader.onload = () => res(reader.result);
288
+ reader.onerror = rej;
289
+ reader.readAsText(blob);
311
290
  });
312
- };
313
- }
314
- async function getAsset(input) {
315
- if (typeof input === 'string') {
316
- // Don't process storage
317
- if (input.startsWith('file:')) return input;
318
-
319
- // Unpack Blobs from react-native BlobManager
320
- if (input.startsWith('blob:')) {
321
- const blob = await new Promise((res, rej) => {
322
- const xhr = new XMLHttpRequest();
323
- xhr.open('GET', input);
324
- xhr.responseType = 'blob';
325
- xhr.onload = () => res(xhr.response);
326
- xhr.onerror = rej;
327
- xhr.send();
328
- });
329
- const data = await new Promise((res, rej) => {
330
- const reader = new FileReader();
331
- reader.onload = () => res(reader.result);
332
- reader.onerror = rej;
333
- reader.readAsText(blob);
334
- });
335
- input = `data:${blob.type};base64,${data}`;
336
- }
291
+ input = `data:${blob.type};base64,${data}`;
292
+ }
337
293
 
338
- // Create safe URI for JSI
339
- if (input.startsWith('data:')) {
340
- const [header, data] = input.split(';base64,');
341
- const [, type] = header.split('/');
342
- const uri = fs.cacheDirectory + uuidv4() + `.${type}`;
343
- await fs.writeAsStringAsync(uri, data, {
344
- encoding: fs.EncodingType.Base64
345
- });
346
- return uri;
347
- }
294
+ // Create safe URI for JSI serialization
295
+ if (input.startsWith('data:')) {
296
+ const [header, data] = input.split(';base64,');
297
+ const [, type] = header.split('/');
298
+ const uri = fs.cacheDirectory + uuidv4() + `.${type}`;
299
+ await fs.writeAsStringAsync(uri, data, {
300
+ encoding: fs.EncodingType.Base64
301
+ });
302
+ return uri;
348
303
  }
304
+ }
349
305
 
350
- // Download bundler module or external URL
351
- const asset = await Asset.fromModule(input).downloadAsync();
352
- let uri = asset.localUri || asset.uri;
306
+ // Download bundler module or external URL
307
+ const asset = await Asset.fromModule(input).downloadAsync();
308
+ let uri = asset.localUri || asset.uri;
353
309
 
354
- // Unpack assets in Android Release Mode
355
- if (!uri.includes(':')) {
356
- const file = `${fs.cacheDirectory}ExponentAsset-${asset.hash}.${asset.type}`;
357
- await fs.copyAsync({
358
- from: uri,
359
- to: file
360
- });
361
- uri = file;
310
+ // Unpack assets in Android Release Mode
311
+ if (!uri.includes(':')) {
312
+ const file = `${fs.cacheDirectory}ExponentAsset-${asset.hash}.${asset.type}`;
313
+ await fs.copyAsync({
314
+ from: uri,
315
+ to: file
316
+ });
317
+ uri = file;
318
+ }
319
+ return uri;
320
+ }
321
+ function polyfills() {
322
+ // Patch Blob for ArrayBuffer and URL if unsupported
323
+ // https://github.com/pmndrs/react-three-fiber/pull/3059
324
+ // https://github.com/pmndrs/react-three-fiber/issues/3058
325
+ if (Platform.OS !== 'web') {
326
+ try {
327
+ const blob = new Blob([new ArrayBuffer(4)]);
328
+ const url = URL.createObjectURL(blob);
329
+ URL.revokeObjectURL(url);
330
+ } catch (_) {
331
+ const BlobManager = require('react-native/Libraries/Blob/BlobManager.js');
332
+ const createObjectURL = URL.createObjectURL;
333
+ URL.createObjectURL = function (blob) {
334
+ if (blob.data._base64) {
335
+ return `data:${blob.type};base64,${blob.data._base64}`;
336
+ }
337
+ return createObjectURL(blob);
338
+ };
339
+ const createFromParts = BlobManager.createFromParts;
340
+ BlobManager.createFromParts = function (parts, options) {
341
+ var _NativeModules$BlobMo2;
342
+ parts = parts.map(part => {
343
+ if (part instanceof ArrayBuffer || ArrayBuffer.isView(part)) {
344
+ part = fromByteArray(new Uint8Array(part));
345
+ }
346
+ return part;
347
+ });
348
+ const blob = createFromParts(parts, options);
349
+ if (!((_NativeModules$BlobMo2 = NativeModules.BlobModule) != null && _NativeModules$BlobMo2.BLOB_URI_SCHEME)) {
350
+ blob.data._base64 = '';
351
+ for (const part of parts) {
352
+ var _data$_base, _data;
353
+ blob.data._base64 += (_data$_base = (_data = part.data) == null ? void 0 : _data._base64) != null ? _data$_base : part;
354
+ }
355
+ }
356
+ return blob;
357
+ };
362
358
  }
363
- return uri;
364
359
  }
365
360
 
366
361
  // Don't pre-process urls, let expo-asset generate an absolute URL
@@ -370,7 +365,6 @@ function polyfills() {
370
365
  // There's no Image in native, so create a data texture instead
371
366
  THREE.TextureLoader.prototype.load = function load(url, onLoad, onProgress, onError) {
372
367
  if (this.path && typeof url === 'string') url = this.path + url;
373
- this.manager.itemStart(url);
374
368
  const texture = new THREE.Texture();
375
369
  getAsset(url).then(async uri => {
376
370
  // https://github.com/expo/expo-three/pull/266
@@ -396,12 +390,7 @@ function polyfills() {
396
390
  // @ts-ignore
397
391
  texture.isDataTexture = true;
398
392
  onLoad == null ? void 0 : onLoad(texture);
399
- }).catch(error => {
400
- onError == null ? void 0 : onError(error);
401
- this.manager.itemError(url);
402
- }).finally(() => {
403
- this.manager.itemEnd(url);
404
- });
393
+ }).catch(onError);
405
394
  return texture;
406
395
  };
407
396
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-three/fiber",
3
- "version": "8.15.2",
3
+ "version": "8.15.4",
4
4
  "description": "A React renderer for Threejs",
5
5
  "keywords": [
6
6
  "react",