@react-three/fiber 8.15.3 → 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,11 @@
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
+
3
9
  ## 8.15.3
4
10
 
5
11
  ### Patch Changes
@@ -282,18 +282,71 @@ 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
- });
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;
298
+
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();
309
+ });
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);
315
+ });
316
+ input = `data:${blob.type};base64,${data}`;
317
+ }
318
+
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;
328
+ }
293
329
  }
294
330
 
295
- // Patch Blob for ArrayBuffer if unsupported
296
- // https://github.com/facebook/react-native/pull/39276
331
+ // Download bundler module or external URL
332
+ const asset = await expoAsset.Asset.fromModule(input).downloadAsync();
333
+ let uri = asset.localUri || asset.uri;
334
+
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
297
350
  if (reactNative.Platform.OS !== 'web') {
298
351
  try {
299
352
  const blob = new Blob([new ArrayBuffer(4)]);
@@ -301,124 +354,34 @@ function polyfills() {
301
354
  URL.revokeObjectURL(url);
302
355
  } catch (_) {
303
356
  const BlobManager = require('react-native/Libraries/Blob/BlobManager.js');
304
- let BLOB_URL_PREFIX = null;
305
- const {
306
- BlobModule
307
- } = reactNative.NativeModules;
308
- if (BlobModule && typeof BlobModule.BLOB_URI_SCHEME === 'string') {
309
- BLOB_URL_PREFIX = BlobModule.BLOB_URI_SCHEME + ':';
310
- if (typeof BlobModule.BLOB_URI_HOST === 'string') {
311
- BLOB_URL_PREFIX += `//${BlobModule.BLOB_URI_HOST}/`;
357
+ const createObjectURL = URL.createObjectURL;
358
+ URL.createObjectURL = function (blob) {
359
+ if (blob.data._base64) {
360
+ return `data:${blob.type};base64,${blob.data._base64}`;
312
361
  }
313
- }
314
- URL.createObjectURL = function createObjectURL(blob) {
315
- const data = blob.data;
316
- if (BLOB_URL_PREFIX === null) {
317
- // https://github.com/pmndrs/react-three-fiber/issues/3058
318
- // throw new Error('Cannot create URL for blob!')
319
- return `data:${blob.type};base64,${data._base64}`;
320
- }
321
- return `${BLOB_URL_PREFIX}${data.blobId}?offset=${data.offset}&size=${blob.size}`;
362
+ return createObjectURL(blob);
322
363
  };
323
- BlobManager.createFromParts = function createFromParts(parts, options) {
324
- const blobId = uuidv4();
325
- const items = parts.map(part => {
364
+ const createFromParts = BlobManager.createFromParts;
365
+ BlobManager.createFromParts = function (parts, options) {
366
+ var _NativeModules$BlobMo2;
367
+ parts = parts.map(part => {
326
368
  if (part instanceof ArrayBuffer || ArrayBuffer.isView(part)) {
327
- const data = base64Js.fromByteArray(new Uint8Array(part));
328
- return {
329
- data,
330
- type: 'string'
331
- };
332
- } else if (part instanceof Blob) {
333
- return {
334
- data: part.data,
335
- type: 'blob'
336
- };
337
- } else {
338
- return {
339
- data: String(part),
340
- type: 'string'
341
- };
342
- }
343
- });
344
- const size = items.reduce((acc, curr) => {
345
- if (curr.type === 'string') {
346
- return acc + global.unescape(encodeURI(curr.data)).length;
347
- } else {
348
- return acc + curr.data.size;
369
+ part = base64Js.fromByteArray(new Uint8Array(part));
349
370
  }
350
- }, 0);
351
- reactNative.NativeModules.BlobModule.createFromParts(items, blobId);
352
- const blob = BlobManager.createFromOptions({
353
- blobId,
354
- offset: 0,
355
- size,
356
- type: options ? options.type : '',
357
- lastModified: options ? options.lastModified : Date.now()
371
+ return part;
358
372
  });
359
- if (BLOB_URL_PREFIX === null) {
360
- let data = '';
361
- for (const item of items) {
362
- var _item$data$_base;
363
- data += (_item$data$_base = item.data._base64) != null ? _item$data$_base : item.data;
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;
364
379
  }
365
- blob.data._base64 = data;
366
380
  }
367
381
  return blob;
368
382
  };
369
383
  }
370
384
  }
371
- async function getAsset(input) {
372
- if (typeof input === 'string') {
373
- // Don't process storage
374
- if (input.startsWith('file:')) return input;
375
-
376
- // Unpack Blobs from react-native BlobManager
377
- if (input.startsWith('blob:')) {
378
- const blob = await new Promise((res, rej) => {
379
- const xhr = new XMLHttpRequest();
380
- xhr.open('GET', input);
381
- xhr.responseType = 'blob';
382
- xhr.onload = () => res(xhr.response);
383
- xhr.onerror = rej;
384
- xhr.send();
385
- });
386
- const data = await new Promise((res, rej) => {
387
- const reader = new FileReader();
388
- reader.onload = () => res(reader.result);
389
- reader.onerror = rej;
390
- reader.readAsText(blob);
391
- });
392
- input = `data:${blob.type};base64,${data}`;
393
- }
394
-
395
- // Create safe URI for JSI
396
- if (input.startsWith('data:')) {
397
- const [header, data] = input.split(';base64,');
398
- const [, type] = header.split('/');
399
- const uri = fs__namespace.cacheDirectory + uuidv4() + `.${type}`;
400
- await fs__namespace.writeAsStringAsync(uri, data, {
401
- encoding: fs__namespace.EncodingType.Base64
402
- });
403
- return uri;
404
- }
405
- }
406
-
407
- // Download bundler module or external URL
408
- const asset = await expoAsset.Asset.fromModule(input).downloadAsync();
409
- let uri = asset.localUri || asset.uri;
410
-
411
- // Unpack assets in Android Release Mode
412
- if (!uri.includes(':')) {
413
- const file = `${fs__namespace.cacheDirectory}ExponentAsset-${asset.hash}.${asset.type}`;
414
- await fs__namespace.copyAsync({
415
- from: uri,
416
- to: file
417
- });
418
- uri = file;
419
- }
420
- return uri;
421
- }
422
385
 
423
386
  // Don't pre-process urls, let expo-asset generate an absolute URL
424
387
  const extractUrlBase = THREE__namespace.LoaderUtils.extractUrlBase.bind(THREE__namespace.LoaderUtils);
@@ -427,7 +390,6 @@ function polyfills() {
427
390
  // There's no Image in native, so create a data texture instead
428
391
  THREE__namespace.TextureLoader.prototype.load = function load(url, onLoad, onProgress, onError) {
429
392
  if (this.path && typeof url === 'string') url = this.path + url;
430
- this.manager.itemStart(url);
431
393
  const texture = new THREE__namespace.Texture();
432
394
  getAsset(url).then(async uri => {
433
395
  // https://github.com/expo/expo-three/pull/266
@@ -453,12 +415,7 @@ function polyfills() {
453
415
  // @ts-ignore
454
416
  texture.isDataTexture = true;
455
417
  onLoad == null ? void 0 : onLoad(texture);
456
- }).catch(error => {
457
- onError == null ? void 0 : onError(error);
458
- this.manager.itemError(url);
459
- }).finally(() => {
460
- this.manager.itemEnd(url);
461
- });
418
+ }).catch(onError);
462
419
  return texture;
463
420
  };
464
421
 
@@ -282,18 +282,71 @@ 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
- });
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;
298
+
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();
309
+ });
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);
315
+ });
316
+ input = `data:${blob.type};base64,${data}`;
317
+ }
318
+
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;
328
+ }
293
329
  }
294
330
 
295
- // Patch Blob for ArrayBuffer if unsupported
296
- // https://github.com/facebook/react-native/pull/39276
331
+ // Download bundler module or external URL
332
+ const asset = await expoAsset.Asset.fromModule(input).downloadAsync();
333
+ let uri = asset.localUri || asset.uri;
334
+
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
297
350
  if (reactNative.Platform.OS !== 'web') {
298
351
  try {
299
352
  const blob = new Blob([new ArrayBuffer(4)]);
@@ -301,124 +354,34 @@ function polyfills() {
301
354
  URL.revokeObjectURL(url);
302
355
  } catch (_) {
303
356
  const BlobManager = require('react-native/Libraries/Blob/BlobManager.js');
304
- let BLOB_URL_PREFIX = null;
305
- const {
306
- BlobModule
307
- } = reactNative.NativeModules;
308
- if (BlobModule && typeof BlobModule.BLOB_URI_SCHEME === 'string') {
309
- BLOB_URL_PREFIX = BlobModule.BLOB_URI_SCHEME + ':';
310
- if (typeof BlobModule.BLOB_URI_HOST === 'string') {
311
- BLOB_URL_PREFIX += `//${BlobModule.BLOB_URI_HOST}/`;
357
+ const createObjectURL = URL.createObjectURL;
358
+ URL.createObjectURL = function (blob) {
359
+ if (blob.data._base64) {
360
+ return `data:${blob.type};base64,${blob.data._base64}`;
312
361
  }
313
- }
314
- URL.createObjectURL = function createObjectURL(blob) {
315
- const data = blob.data;
316
- if (BLOB_URL_PREFIX === null) {
317
- // https://github.com/pmndrs/react-three-fiber/issues/3058
318
- // throw new Error('Cannot create URL for blob!')
319
- return `data:${blob.type};base64,${data._base64}`;
320
- }
321
- return `${BLOB_URL_PREFIX}${data.blobId}?offset=${data.offset}&size=${blob.size}`;
362
+ return createObjectURL(blob);
322
363
  };
323
- BlobManager.createFromParts = function createFromParts(parts, options) {
324
- const blobId = uuidv4();
325
- const items = parts.map(part => {
364
+ const createFromParts = BlobManager.createFromParts;
365
+ BlobManager.createFromParts = function (parts, options) {
366
+ var _NativeModules$BlobMo2;
367
+ parts = parts.map(part => {
326
368
  if (part instanceof ArrayBuffer || ArrayBuffer.isView(part)) {
327
- const data = base64Js.fromByteArray(new Uint8Array(part));
328
- return {
329
- data,
330
- type: 'string'
331
- };
332
- } else if (part instanceof Blob) {
333
- return {
334
- data: part.data,
335
- type: 'blob'
336
- };
337
- } else {
338
- return {
339
- data: String(part),
340
- type: 'string'
341
- };
342
- }
343
- });
344
- const size = items.reduce((acc, curr) => {
345
- if (curr.type === 'string') {
346
- return acc + global.unescape(encodeURI(curr.data)).length;
347
- } else {
348
- return acc + curr.data.size;
369
+ part = base64Js.fromByteArray(new Uint8Array(part));
349
370
  }
350
- }, 0);
351
- reactNative.NativeModules.BlobModule.createFromParts(items, blobId);
352
- const blob = BlobManager.createFromOptions({
353
- blobId,
354
- offset: 0,
355
- size,
356
- type: options ? options.type : '',
357
- lastModified: options ? options.lastModified : Date.now()
371
+ return part;
358
372
  });
359
- if (BLOB_URL_PREFIX === null) {
360
- let data = '';
361
- for (const item of items) {
362
- var _item$data$_base;
363
- data += (_item$data$_base = item.data._base64) != null ? _item$data$_base : item.data;
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;
364
379
  }
365
- blob.data._base64 = data;
366
380
  }
367
381
  return blob;
368
382
  };
369
383
  }
370
384
  }
371
- async function getAsset(input) {
372
- if (typeof input === 'string') {
373
- // Don't process storage
374
- if (input.startsWith('file:')) return input;
375
-
376
- // Unpack Blobs from react-native BlobManager
377
- if (input.startsWith('blob:')) {
378
- const blob = await new Promise((res, rej) => {
379
- const xhr = new XMLHttpRequest();
380
- xhr.open('GET', input);
381
- xhr.responseType = 'blob';
382
- xhr.onload = () => res(xhr.response);
383
- xhr.onerror = rej;
384
- xhr.send();
385
- });
386
- const data = await new Promise((res, rej) => {
387
- const reader = new FileReader();
388
- reader.onload = () => res(reader.result);
389
- reader.onerror = rej;
390
- reader.readAsText(blob);
391
- });
392
- input = `data:${blob.type};base64,${data}`;
393
- }
394
-
395
- // Create safe URI for JSI
396
- if (input.startsWith('data:')) {
397
- const [header, data] = input.split(';base64,');
398
- const [, type] = header.split('/');
399
- const uri = fs__namespace.cacheDirectory + uuidv4() + `.${type}`;
400
- await fs__namespace.writeAsStringAsync(uri, data, {
401
- encoding: fs__namespace.EncodingType.Base64
402
- });
403
- return uri;
404
- }
405
- }
406
-
407
- // Download bundler module or external URL
408
- const asset = await expoAsset.Asset.fromModule(input).downloadAsync();
409
- let uri = asset.localUri || asset.uri;
410
-
411
- // Unpack assets in Android Release Mode
412
- if (!uri.includes(':')) {
413
- const file = `${fs__namespace.cacheDirectory}ExponentAsset-${asset.hash}.${asset.type}`;
414
- await fs__namespace.copyAsync({
415
- from: uri,
416
- to: file
417
- });
418
- uri = file;
419
- }
420
- return uri;
421
- }
422
385
 
423
386
  // Don't pre-process urls, let expo-asset generate an absolute URL
424
387
  const extractUrlBase = THREE__namespace.LoaderUtils.extractUrlBase.bind(THREE__namespace.LoaderUtils);
@@ -427,7 +390,6 @@ function polyfills() {
427
390
  // There's no Image in native, so create a data texture instead
428
391
  THREE__namespace.TextureLoader.prototype.load = function load(url, onLoad, onProgress, onError) {
429
392
  if (this.path && typeof url === 'string') url = this.path + url;
430
- this.manager.itemStart(url);
431
393
  const texture = new THREE__namespace.Texture();
432
394
  getAsset(url).then(async uri => {
433
395
  // https://github.com/expo/expo-three/pull/266
@@ -453,12 +415,7 @@ function polyfills() {
453
415
  // @ts-ignore
454
416
  texture.isDataTexture = true;
455
417
  onLoad == null ? void 0 : onLoad(texture);
456
- }).catch(error => {
457
- onError == null ? void 0 : onError(error);
458
- this.manager.itemError(url);
459
- }).finally(() => {
460
- this.manager.itemEnd(url);
461
- });
418
+ }).catch(onError);
462
419
  return texture;
463
420
  };
464
421
 
@@ -257,18 +257,71 @@ 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
- });
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;
273
+
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();
284
+ });
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);
290
+ });
291
+ input = `data:${blob.type};base64,${data}`;
292
+ }
293
+
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;
303
+ }
268
304
  }
269
305
 
270
- // Patch Blob for ArrayBuffer if unsupported
271
- // https://github.com/facebook/react-native/pull/39276
306
+ // Download bundler module or external URL
307
+ const asset = await Asset.fromModule(input).downloadAsync();
308
+ let uri = asset.localUri || asset.uri;
309
+
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
272
325
  if (Platform.OS !== 'web') {
273
326
  try {
274
327
  const blob = new Blob([new ArrayBuffer(4)]);
@@ -276,124 +329,34 @@ function polyfills() {
276
329
  URL.revokeObjectURL(url);
277
330
  } catch (_) {
278
331
  const BlobManager = require('react-native/Libraries/Blob/BlobManager.js');
279
- let BLOB_URL_PREFIX = null;
280
- const {
281
- BlobModule
282
- } = NativeModules;
283
- if (BlobModule && typeof BlobModule.BLOB_URI_SCHEME === 'string') {
284
- BLOB_URL_PREFIX = BlobModule.BLOB_URI_SCHEME + ':';
285
- if (typeof BlobModule.BLOB_URI_HOST === 'string') {
286
- BLOB_URL_PREFIX += `//${BlobModule.BLOB_URI_HOST}/`;
332
+ const createObjectURL = URL.createObjectURL;
333
+ URL.createObjectURL = function (blob) {
334
+ if (blob.data._base64) {
335
+ return `data:${blob.type};base64,${blob.data._base64}`;
287
336
  }
288
- }
289
- URL.createObjectURL = function createObjectURL(blob) {
290
- const data = blob.data;
291
- if (BLOB_URL_PREFIX === null) {
292
- // https://github.com/pmndrs/react-three-fiber/issues/3058
293
- // throw new Error('Cannot create URL for blob!')
294
- return `data:${blob.type};base64,${data._base64}`;
295
- }
296
- return `${BLOB_URL_PREFIX}${data.blobId}?offset=${data.offset}&size=${blob.size}`;
337
+ return createObjectURL(blob);
297
338
  };
298
- BlobManager.createFromParts = function createFromParts(parts, options) {
299
- const blobId = uuidv4();
300
- const items = parts.map(part => {
339
+ const createFromParts = BlobManager.createFromParts;
340
+ BlobManager.createFromParts = function (parts, options) {
341
+ var _NativeModules$BlobMo2;
342
+ parts = parts.map(part => {
301
343
  if (part instanceof ArrayBuffer || ArrayBuffer.isView(part)) {
302
- const data = fromByteArray(new Uint8Array(part));
303
- return {
304
- data,
305
- type: 'string'
306
- };
307
- } else if (part instanceof Blob) {
308
- return {
309
- data: part.data,
310
- type: 'blob'
311
- };
312
- } else {
313
- return {
314
- data: String(part),
315
- type: 'string'
316
- };
317
- }
318
- });
319
- const size = items.reduce((acc, curr) => {
320
- if (curr.type === 'string') {
321
- return acc + global.unescape(encodeURI(curr.data)).length;
322
- } else {
323
- return acc + curr.data.size;
344
+ part = fromByteArray(new Uint8Array(part));
324
345
  }
325
- }, 0);
326
- NativeModules.BlobModule.createFromParts(items, blobId);
327
- const blob = BlobManager.createFromOptions({
328
- blobId,
329
- offset: 0,
330
- size,
331
- type: options ? options.type : '',
332
- lastModified: options ? options.lastModified : Date.now()
346
+ return part;
333
347
  });
334
- if (BLOB_URL_PREFIX === null) {
335
- let data = '';
336
- for (const item of items) {
337
- var _item$data$_base;
338
- data += (_item$data$_base = item.data._base64) != null ? _item$data$_base : item.data;
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;
339
354
  }
340
- blob.data._base64 = data;
341
355
  }
342
356
  return blob;
343
357
  };
344
358
  }
345
359
  }
346
- async function getAsset(input) {
347
- if (typeof input === 'string') {
348
- // Don't process storage
349
- if (input.startsWith('file:')) return input;
350
-
351
- // Unpack Blobs from react-native BlobManager
352
- if (input.startsWith('blob:')) {
353
- const blob = await new Promise((res, rej) => {
354
- const xhr = new XMLHttpRequest();
355
- xhr.open('GET', input);
356
- xhr.responseType = 'blob';
357
- xhr.onload = () => res(xhr.response);
358
- xhr.onerror = rej;
359
- xhr.send();
360
- });
361
- const data = await new Promise((res, rej) => {
362
- const reader = new FileReader();
363
- reader.onload = () => res(reader.result);
364
- reader.onerror = rej;
365
- reader.readAsText(blob);
366
- });
367
- input = `data:${blob.type};base64,${data}`;
368
- }
369
-
370
- // Create safe URI for JSI
371
- if (input.startsWith('data:')) {
372
- const [header, data] = input.split(';base64,');
373
- const [, type] = header.split('/');
374
- const uri = fs.cacheDirectory + uuidv4() + `.${type}`;
375
- await fs.writeAsStringAsync(uri, data, {
376
- encoding: fs.EncodingType.Base64
377
- });
378
- return uri;
379
- }
380
- }
381
-
382
- // Download bundler module or external URL
383
- const asset = await Asset.fromModule(input).downloadAsync();
384
- let uri = asset.localUri || asset.uri;
385
-
386
- // Unpack assets in Android Release Mode
387
- if (!uri.includes(':')) {
388
- const file = `${fs.cacheDirectory}ExponentAsset-${asset.hash}.${asset.type}`;
389
- await fs.copyAsync({
390
- from: uri,
391
- to: file
392
- });
393
- uri = file;
394
- }
395
- return uri;
396
- }
397
360
 
398
361
  // Don't pre-process urls, let expo-asset generate an absolute URL
399
362
  const extractUrlBase = THREE.LoaderUtils.extractUrlBase.bind(THREE.LoaderUtils);
@@ -402,7 +365,6 @@ function polyfills() {
402
365
  // There's no Image in native, so create a data texture instead
403
366
  THREE.TextureLoader.prototype.load = function load(url, onLoad, onProgress, onError) {
404
367
  if (this.path && typeof url === 'string') url = this.path + url;
405
- this.manager.itemStart(url);
406
368
  const texture = new THREE.Texture();
407
369
  getAsset(url).then(async uri => {
408
370
  // https://github.com/expo/expo-three/pull/266
@@ -428,12 +390,7 @@ function polyfills() {
428
390
  // @ts-ignore
429
391
  texture.isDataTexture = true;
430
392
  onLoad == null ? void 0 : onLoad(texture);
431
- }).catch(error => {
432
- onError == null ? void 0 : onError(error);
433
- this.manager.itemError(url);
434
- }).finally(() => {
435
- this.manager.itemEnd(url);
436
- });
393
+ }).catch(onError);
437
394
  return texture;
438
395
  };
439
396
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-three/fiber",
3
- "version": "8.15.3",
3
+ "version": "8.15.4",
4
4
  "description": "A React renderer for Threejs",
5
5
  "keywords": [
6
6
  "react",