Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 10 additions & 17 deletions packages/react-native/Libraries/Core/polyfillPromise.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,22 @@

'use strict';

const {polyfillGlobal} = require('../Utilities/PolyfillFunctions');

/**
* Set up Promise. The native Promise implementation throws the following error:
* ERROR: Event loop not supported.
* Set up Promise. Hermes provides a native Promise implementation that
* satisfies all requirements of React Native.
*
* If you don't need these polyfills, don't use InitializeCore; just directly
* require the modules you need from InitializeCore for setup.
*/

// If global.Promise is provided by Hermes, we are confident that it can provide
// all the methods needed by React Native, so we can directly use it.
if (global?.HermesInternal?.hasPromise?.()) {
const HermesPromise = global.Promise;
// Hermes is the only supported JS engine and always provides Promise natively.
const HermesPromise = global.Promise;

if (__DEV__) {
if (typeof HermesPromise !== 'function') {
console.error('HermesPromise does not exist');
}
global.HermesInternal?.enablePromiseRejectionTracker?.(
require('../promiseRejectionTrackingOptions').default,
);
if (__DEV__) {
if (typeof HermesPromise !== 'function') {
console.error('HermesPromise does not exist');
}
} else {
polyfillGlobal('Promise', () => require('../Promise').default);
global.HermesInternal?.enablePromiseRejectionTracker?.(
require('../promiseRejectionTrackingOptions').default,
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import com.facebook.drawee.backends.pipeline.Fresco
import com.facebook.fbreact.specs.NativeImageLoaderAndroidSpec
import com.facebook.imagepipeline.common.RotationOptions
import com.facebook.imagepipeline.core.ImagePipeline
import com.facebook.imagepipeline.image.CloseableImage
import com.facebook.imagepipeline.image.EncodedImage
import com.facebook.imagepipeline.request.ImageRequest
import com.facebook.imagepipeline.request.ImageRequestBuilder
Expand Down Expand Up @@ -93,6 +94,13 @@ internal class ImageLoaderModule : NativeImageLoaderAndroidSpec, LifecycleEventL
resolveResourceSize(uriString, promise)
return
}
// Fast path: data: URIs are not supported by fetchEncodedImage's producer
// sequence (throws IllegalArgumentException). Route them through the decoded
// image pipeline which handles data: URIs via DataFetchProducer.
if ("data" == source.uri.scheme) {
resolveDecodedImageSize(source, promise)
return
}
val request: ImageRequest =
ImageRequestBuilder.newBuilderWithSource(source.uri)
.setRotationOptions(RotationOptions.disableRotation())
Expand Down Expand Up @@ -122,6 +130,11 @@ internal class ImageLoaderModule : NativeImageLoaderAndroidSpec, LifecycleEventL
resolveResourceSize(uriString, promise)
return
}
// Fast path: data: URIs are self-contained; headers are not applicable.
if ("data" == source.uri.scheme) {
resolveDecodedImageSize(source, promise)
return
}
val imageRequestBuilder: ImageRequestBuilder =
ImageRequestBuilder.newBuilderWithSource(source.uri)
.setRotationOptions(RotationOptions.disableRotation())
Expand Down Expand Up @@ -217,6 +230,59 @@ internal class ImageLoaderModule : NativeImageLoaderAndroidSpec, LifecycleEventL
)
}

/**
* Resolve the size of a data: URI (or any URI unsupported by the encoded-image pipeline)
* by decoding the image through Fresco's decoded-image pipeline, which routes through
* DataFetchProducer and supports data: URIs.
*/
private fun resolveDecodedImageSize(source: ImageSource, promise: Promise) {
val request: ImageRequest = ImageRequestBuilder.newBuilderWithSource(source.uri).build()
val dataSource: DataSource<CloseableReference<CloseableImage>> =
this.imagePipeline.fetchDecodedImage(request, this.callerContext)
dataSource.subscribe(
object : BaseDataSubscriber<CloseableReference<CloseableImage>>() {
override fun onNewResultImpl(
dataSource: DataSource<CloseableReference<CloseableImage>>
) {
if (!dataSource.isFinished) {
return
}
val ref = dataSource.result
if (ref != null) {
try {
val image = ref.get()
val width = image.width
val height = image.height
if (width < 0 || height < 0) {
promise.reject(ERROR_GET_SIZE_FAILURE, "Failed to get the size of the image")
return
}
promise.resolve(
buildReadableMap {
put("width", width)
put("height", height)
},
)
} catch (e: Exception) {
promise.reject(ERROR_GET_SIZE_FAILURE, e)
} finally {
CloseableReference.closeSafely(ref)
}
} else {
promise.reject(ERROR_GET_SIZE_FAILURE, "Failed to get the size of the image")
}
}

override fun onFailureImpl(
dataSource: DataSource<CloseableReference<CloseableImage>>
) {
promise.reject(ERROR_GET_SIZE_FAILURE, dataSource.failureCause)
}
},
CallerThreadExecutor.getInstance(),
)
}

/**
* Prefetches the given image to the Fresco image disk cache.
*
Expand Down