/
resolveAssetSource.js
143 lines (122 loc) · 4.22 KB
/
resolveAssetSource.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow strict-local
*/
// Utilities for resolving an asset into a `source` for e.g. `Image`
import type {ResolvedAssetSource} from './AssetSourceResolver';
import type {ImageSource} from './ImageSource';
import SourceCode from '../NativeModules/specs/NativeSourceCode';
const AssetSourceResolver = require('./AssetSourceResolver');
const {pickScale} = require('./AssetUtils');
const AssetRegistry = require('@react-native/assets-registry/registry');
type CustomSourceTransformer = (
resolver: AssetSourceResolver,
) => ?ResolvedAssetSource;
let _customSourceTransformers: Array<CustomSourceTransformer> = [];
let _serverURL: ?string;
let _scriptURL: ?string;
let _sourceCodeScriptURL: ?string;
function getSourceCodeScriptURL(): ?string {
if (_sourceCodeScriptURL != null) {
return _sourceCodeScriptURL;
}
_sourceCodeScriptURL = SourceCode.getConstants().scriptURL;
return _sourceCodeScriptURL;
}
function getDevServerURL(): ?string {
if (_serverURL === undefined) {
const sourceCodeScriptURL = getSourceCodeScriptURL();
const match = sourceCodeScriptURL?.match(/^https?:\/\/.*?\//);
if (match) {
// jsBundle was loaded from network
_serverURL = match[0];
} else {
// jsBundle was loaded from file
_serverURL = null;
}
}
return _serverURL;
}
function _coerceLocalScriptURL(scriptURL: ?string): ?string {
let normalizedScriptURL = scriptURL;
if (normalizedScriptURL != null) {
if (normalizedScriptURL.startsWith('assets://')) {
// android: running from within assets, no offline path to use
return null;
}
normalizedScriptURL = normalizedScriptURL.substring(
0,
normalizedScriptURL.lastIndexOf('/') + 1,
);
if (!normalizedScriptURL.includes('://')) {
// Add file protocol in case we have an absolute file path and not a URL.
// This shouldn't really be necessary. scriptURL should be a URL.
normalizedScriptURL = 'file://' + normalizedScriptURL;
}
}
return normalizedScriptURL;
}
function getScriptURL(): ?string {
if (_scriptURL === undefined) {
_scriptURL = _coerceLocalScriptURL(getSourceCodeScriptURL());
}
return _scriptURL;
}
/**
* `transformer` can optionally be used to apply a custom transformation when
* resolving an asset source. This methods overrides all other custom transformers
* that may have been previously registered.
*/
function setCustomSourceTransformer(
transformer: CustomSourceTransformer,
): void {
_customSourceTransformers = [transformer];
}
/**
* Adds a `transformer` into the chain of custom source transformers, which will
* be applied in the order registered, until one returns a non-null value.
*/
function addCustomSourceTransformer(
transformer: CustomSourceTransformer,
): void {
_customSourceTransformers.push(transformer);
}
/**
* `source` is either a number (opaque type returned by require('./foo.png'))
* or an `ImageSource` like { uri: '<http location || file path>' }
*/
function resolveAssetSource(source: ?ImageSource): ?ResolvedAssetSource {
if (source == null || typeof source === 'object') {
// $FlowFixMe[incompatible-exact] `source` doesn't exactly match `ResolvedAssetSource`
// $FlowFixMe[incompatible-return] `source` doesn't exactly match `ResolvedAssetSource`
return source;
}
const asset = AssetRegistry.getAssetByID(source);
if (!asset) {
return null;
}
const resolver = new AssetSourceResolver(
getDevServerURL(),
getScriptURL(),
asset,
);
// Apply (chained) custom source transformers, if any
if (_customSourceTransformers) {
for (const customSourceTransformer of _customSourceTransformers) {
const transformedSource = customSourceTransformer(resolver);
if (transformedSource != null) {
return transformedSource;
}
}
}
return resolver.defaultAsset();
}
resolveAssetSource.pickScale = pickScale;
resolveAssetSource.setCustomSourceTransformer = setCustomSourceTransformer;
resolveAssetSource.addCustomSourceTransformer = addCustomSourceTransformer;
module.exports = resolveAssetSource;