@lwrjs/loader 0.12.0-alpha.9 → 0.13.0-alpha.0
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/build/assets/prod/lwr-error-shim.js +1 -1
- package/build/assets/prod/lwr-loader-shim-legacy.bundle.js +168 -133
- package/build/assets/prod/lwr-loader-shim-legacy.bundle.min.js +3 -3
- package/build/assets/prod/lwr-loader-shim-legacy.js +6 -5
- package/build/assets/prod/lwr-loader-shim.bundle.js +167 -134
- package/build/assets/prod/lwr-loader-shim.bundle.min.js +3 -3
- package/build/assets/prod/lwr-loader-shim.js +6 -5
- package/build/cjs/modules/lwr/loader/moduleRegistry/moduleRegistry.cjs +88 -68
- package/build/cjs/modules/lwr/loaderLegacy/moduleRegistry/moduleRegistry.cjs +88 -68
- package/build/modules/lwr/esmLoader/esmLoader.js +1 -1
- package/build/modules/lwr/loader/loader.js +161 -129
- package/build/modules/lwr/loaderLegacy/loaderLegacy.js +162 -128
- package/package.json +7 -7
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* SPDX-License-Identifier: MIT
|
|
5
5
|
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
|
|
6
6
|
*/
|
|
7
|
-
/* LWR Module Loader v0.
|
|
7
|
+
/* LWR Module Loader v0.13.0-alpha.0 */
|
|
8
8
|
const templateRegex = /\{([0-9]+)\}/g;
|
|
9
9
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
10
10
|
function templateString(template, args) {
|
|
@@ -646,7 +646,7 @@ try {
|
|
|
646
646
|
// swallow
|
|
647
647
|
}
|
|
648
648
|
const trusted = createPolicy('trusted', policyOptions);
|
|
649
|
-
/*! version: 0.21.
|
|
649
|
+
/*! version: 0.21.4 */
|
|
650
650
|
|
|
651
651
|
/* global console,process */
|
|
652
652
|
|
|
@@ -798,22 +798,13 @@ async function evaluateLoadHook(
|
|
|
798
798
|
|
|
799
799
|
|
|
800
800
|
|
|
801
|
+
|
|
802
|
+
|
|
801
803
|
|
|
802
804
|
|
|
803
805
|
|
|
804
806
|
class ModuleRegistry {
|
|
805
807
|
|
|
806
|
-
|
|
807
|
-
// A registry for named AMD defines containing the *metadata* of AMD module
|
|
808
|
-
__init() {this.namedDefineRegistry = new Map();}
|
|
809
|
-
// The evaluated module registry where the module identifier (name or URL?) is the key
|
|
810
|
-
__init2() {this.moduleRegistry = new Map();}
|
|
811
|
-
// Aliases of modules in the registry
|
|
812
|
-
__init3() {this.aliases = new Map();}
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
808
|
|
|
818
809
|
constructor(config) {ModuleRegistry.prototype.__init.call(this);ModuleRegistry.prototype.__init2.call(this);ModuleRegistry.prototype.__init3.call(this);
|
|
819
810
|
this.profiler = config.profiler;
|
|
@@ -823,9 +814,6 @@ class ModuleRegistry {
|
|
|
823
814
|
);
|
|
824
815
|
}
|
|
825
816
|
|
|
826
|
-
/**
|
|
827
|
-
* Module import
|
|
828
|
-
*/
|
|
829
817
|
async load(id, importer) {
|
|
830
818
|
const metadata = importer ? { importer } : {};
|
|
831
819
|
this.profiler.logOperationStart({
|
|
@@ -833,23 +821,18 @@ class ModuleRegistry {
|
|
|
833
821
|
specifier: id,
|
|
834
822
|
metadata,
|
|
835
823
|
});
|
|
836
|
-
|
|
837
824
|
const resolvedId = await this.resolve(id, importer);
|
|
838
|
-
const moduleRecord = this.getModuleRecord(resolvedId, id);
|
|
839
|
-
|
|
825
|
+
const moduleRecord = await this.getModuleRecord(resolvedId, id);
|
|
840
826
|
if (moduleRecord.evaluated) {
|
|
841
827
|
return moduleRecord.module;
|
|
842
828
|
} else {
|
|
843
829
|
if (!moduleRecord.evaluationPromise) {
|
|
844
|
-
moduleRecord.evaluationPromise = this.
|
|
830
|
+
moduleRecord.evaluationPromise = this.topLevelEvaluation(moduleRecord);
|
|
845
831
|
}
|
|
846
832
|
return moduleRecord.evaluationPromise;
|
|
847
833
|
}
|
|
848
834
|
}
|
|
849
835
|
|
|
850
|
-
/**
|
|
851
|
-
* Resolve id for a module
|
|
852
|
-
*/
|
|
853
836
|
async resolve(id, importer) {
|
|
854
837
|
const parentUrl = this.resolver.getBaseUrl(); // only support baseUrl for now
|
|
855
838
|
|
|
@@ -865,7 +848,7 @@ class ModuleRegistry {
|
|
|
865
848
|
// eslint-disable-next-line no-await-in-loop
|
|
866
849
|
result = isResponseAPromise(response) ? await response : response;
|
|
867
850
|
}
|
|
868
|
-
if (!isValidResolveResponse(result)) {
|
|
851
|
+
if (!this.isValidResolveResponse(result)) {
|
|
869
852
|
throw new LoaderError(INVALID_LOADER_SERVICE_RESPONSE);
|
|
870
853
|
}
|
|
871
854
|
|
|
@@ -951,9 +934,6 @@ class ModuleRegistry {
|
|
|
951
934
|
return this.moduleRegistry.has(id);
|
|
952
935
|
}
|
|
953
936
|
|
|
954
|
-
/**
|
|
955
|
-
* Module entry point LWR.define()
|
|
956
|
-
*/
|
|
957
937
|
define(name, dependencies, exporter) {
|
|
958
938
|
const mod = this.namedDefineRegistry.get(name);
|
|
959
939
|
// Don't allow redefining a module.
|
|
@@ -1020,6 +1000,19 @@ class ModuleRegistry {
|
|
|
1020
1000
|
});
|
|
1021
1001
|
}
|
|
1022
1002
|
|
|
1003
|
+
|
|
1004
|
+
|
|
1005
|
+
// A registry for named AMD defines containing the *metadata* of AMD module
|
|
1006
|
+
__init() {this.namedDefineRegistry = new Map();}
|
|
1007
|
+
|
|
1008
|
+
// The evaluated module registry where the module identifier (name or URL?) is the key
|
|
1009
|
+
__init2() {this.moduleRegistry = new Map();}
|
|
1010
|
+
|
|
1011
|
+
// Aliases of modules in the registry
|
|
1012
|
+
__init3() {this.aliases = new Map();}
|
|
1013
|
+
|
|
1014
|
+
|
|
1015
|
+
|
|
1023
1016
|
getImportMetadataResolver() {
|
|
1024
1017
|
return this.resolver;
|
|
1025
1018
|
}
|
|
@@ -1045,7 +1038,7 @@ class ModuleRegistry {
|
|
|
1045
1038
|
return moduleRecord;
|
|
1046
1039
|
}
|
|
1047
1040
|
|
|
1048
|
-
getModuleRecord(resolvedId, id) {
|
|
1041
|
+
async getModuleRecord(resolvedId, id) {
|
|
1049
1042
|
// Look for an existing record
|
|
1050
1043
|
const existingRecord = this.getExistingModuleRecord(resolvedId, id);
|
|
1051
1044
|
if (existingRecord) {
|
|
@@ -1053,10 +1046,29 @@ class ModuleRegistry {
|
|
|
1053
1046
|
return existingRecord;
|
|
1054
1047
|
}
|
|
1055
1048
|
|
|
1049
|
+
// Create a new Module Record
|
|
1050
|
+
const instantiation = this.getModuleDef(resolvedId, id);
|
|
1051
|
+
const dependencyRecords = instantiation.then((moduleDef) => {
|
|
1052
|
+
const dependencies = moduleDef.dependencies || [];
|
|
1053
|
+
// get dep and filter out exports
|
|
1054
|
+
const filtered = dependencies
|
|
1055
|
+
.map((dep) => {
|
|
1056
|
+
if (dep === 'exports') {
|
|
1057
|
+
return;
|
|
1058
|
+
}
|
|
1059
|
+
invariant(dep !== 'require', NO_AMD_REQUIRE);
|
|
1060
|
+
return this.getModuleDependencyRecord.call(this, dep);
|
|
1061
|
+
})
|
|
1062
|
+
.filter((depRecord) => depRecord !== undefined) ;
|
|
1063
|
+
|
|
1064
|
+
return Promise.all(filtered);
|
|
1065
|
+
});
|
|
1066
|
+
|
|
1056
1067
|
const newModuleRecord = {
|
|
1057
1068
|
id: resolvedId,
|
|
1058
1069
|
module: Object.create(null),
|
|
1059
|
-
|
|
1070
|
+
dependencyRecords,
|
|
1071
|
+
instantiation,
|
|
1060
1072
|
evaluated: false,
|
|
1061
1073
|
evaluationPromise: null,
|
|
1062
1074
|
};
|
|
@@ -1064,7 +1076,8 @@ class ModuleRegistry {
|
|
|
1064
1076
|
this.moduleRegistry.set(resolvedId, newModuleRecord);
|
|
1065
1077
|
this.storeModuleAlias(id, resolvedId);
|
|
1066
1078
|
|
|
1067
|
-
return
|
|
1079
|
+
// Wait for the dependencies to resolve the return the moduleRecord
|
|
1080
|
+
return dependencyRecords.then(() => newModuleRecord);
|
|
1068
1081
|
}
|
|
1069
1082
|
|
|
1070
1083
|
storeModuleAlias(aliasId, resolvedId) {
|
|
@@ -1085,87 +1098,95 @@ class ModuleRegistry {
|
|
|
1085
1098
|
}
|
|
1086
1099
|
}
|
|
1087
1100
|
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
async evaluateDependencies(
|
|
1092
|
-
dependencies,
|
|
1093
|
-
evaluationMap,
|
|
1094
|
-
) {
|
|
1095
|
-
const exports = {};
|
|
1096
|
-
const promiseArray = [];
|
|
1097
|
-
|
|
1098
|
-
if (dependencies) {
|
|
1099
|
-
for (const dep of dependencies) {
|
|
1100
|
-
if (dep === 'exports') {
|
|
1101
|
-
promiseArray.push(Promise.resolve(exports));
|
|
1102
|
-
} else {
|
|
1103
|
-
invariant(dep !== 'require', NO_AMD_REQUIRE);
|
|
1104
|
-
promiseArray.push(this.evaluateDependent(dep, evaluationMap));
|
|
1105
|
-
}
|
|
1106
|
-
}
|
|
1107
|
-
}
|
|
1108
|
-
|
|
1109
|
-
return Promise.all(promiseArray).then((results) => {
|
|
1110
|
-
const depsMapped = results.filter((result) => result !== undefined);
|
|
1111
|
-
return { depsMapped, exports };
|
|
1112
|
-
});
|
|
1101
|
+
async getModuleDependencyRecord(dependency) {
|
|
1102
|
+
const resolvedDepId = await this.resolve(dependency);
|
|
1103
|
+
return this.getModuleRecord(resolvedDepId, dependency);
|
|
1113
1104
|
}
|
|
1114
1105
|
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
const handleReturn = (module) => {
|
|
1122
|
-
if (module) {
|
|
1123
|
-
return module.__defaultInterop ? module.default : module;
|
|
1124
|
-
}
|
|
1125
|
-
throw new LoaderError(FAILED_DEP, [resolvedDepId]);
|
|
1126
|
-
};
|
|
1106
|
+
// execute the "top-level code" (the code outside of functions) of a module
|
|
1107
|
+
async topLevelEvaluation(moduleRecord) {
|
|
1108
|
+
await this.instantiateAll(moduleRecord, {});
|
|
1109
|
+
return this.evaluateModule(moduleRecord, {});
|
|
1110
|
+
}
|
|
1127
1111
|
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1112
|
+
// Returns a promise when a module and all of it's dependencies have finished instantiation
|
|
1113
|
+
async instantiateAll(
|
|
1114
|
+
moduleRecord,
|
|
1115
|
+
instantiatedMap,
|
|
1116
|
+
) {
|
|
1117
|
+
if (!instantiatedMap[moduleRecord.id]) {
|
|
1118
|
+
instantiatedMap[moduleRecord.id] = true;
|
|
1119
|
+
const dependencyModuleRecords = await moduleRecord.dependencyRecords;
|
|
1120
|
+
if (dependencyModuleRecords) {
|
|
1121
|
+
for (let i = 0; i < dependencyModuleRecords.length; i++) {
|
|
1122
|
+
const depRecord = dependencyModuleRecords[i];
|
|
1123
|
+
// eslint-disable-next-line no-await-in-loop
|
|
1124
|
+
await this.instantiateAll(depRecord, instantiatedMap);
|
|
1125
|
+
}
|
|
1142
1126
|
}
|
|
1143
|
-
return depModuleRecord.evaluationPromise.then((module) => {
|
|
1144
|
-
return handleReturn(module);
|
|
1145
|
-
});
|
|
1146
|
-
} else {
|
|
1147
|
-
// Otherwise return a dummy circular module wrapper
|
|
1148
|
-
module = getCircularDependencyWrapper(module);
|
|
1149
1127
|
}
|
|
1150
|
-
return handleReturn(module);
|
|
1151
1128
|
}
|
|
1152
1129
|
|
|
1153
1130
|
async evaluateModule(
|
|
1154
1131
|
moduleRecord,
|
|
1155
1132
|
evaluationMap,
|
|
1156
1133
|
) {
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1134
|
+
const dependencyModuleRecords = await moduleRecord.dependencyRecords;
|
|
1135
|
+
if (dependencyModuleRecords.length > 0) {
|
|
1136
|
+
evaluationMap[moduleRecord.id] = true;
|
|
1137
|
+
// evaluate dependencies first
|
|
1138
|
+
await this.evaluateModuleDependencies(dependencyModuleRecords, evaluationMap);
|
|
1139
|
+
}
|
|
1160
1140
|
|
|
1161
|
-
// Wait for load to finish
|
|
1162
1141
|
const { exporter, dependencies } = await moduleRecord.instantiation;
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
const
|
|
1142
|
+
// The exports object automatically gets filled in by the exporter evaluation
|
|
1143
|
+
const exports = {};
|
|
1144
|
+
const depsMapped = dependencies
|
|
1145
|
+
? await Promise.all(
|
|
1146
|
+
dependencies.map(async (dep) => {
|
|
1147
|
+
if (dep === 'exports') {
|
|
1148
|
+
return exports;
|
|
1149
|
+
}
|
|
1150
|
+
const resolvedDepId = await this.resolve(dep);
|
|
1151
|
+
|
|
1152
|
+
const moduleRecord = this.moduleRegistry.get(resolvedDepId) ;
|
|
1153
|
+
if (!moduleRecord) {
|
|
1154
|
+
throw new LoaderError(FAILED_DEP, [resolvedDepId]);
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
const module = moduleRecord.module;
|
|
1158
|
+
|
|
1159
|
+
/**
|
|
1160
|
+
* Circular dependencies are handled properly when named exports are used,
|
|
1161
|
+
* however, for default exports there is a bug: https://github.com/rollup/rollup/issues/3384
|
|
1162
|
+
*
|
|
1163
|
+
* The workaround below applies for circular dependencies (!moduleRecord.evaluated)
|
|
1164
|
+
*/
|
|
1165
|
+
if (!moduleRecord.evaluated) {
|
|
1166
|
+
return this.getCircularDependencyWrapper(module);
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
if (module) {
|
|
1170
|
+
return module.__defaultInterop ? module.default : module;
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
throw new LoaderError(FAILED_DEP, [resolvedDepId]);
|
|
1174
|
+
}),
|
|
1175
|
+
)
|
|
1176
|
+
: [];
|
|
1177
|
+
|
|
1178
|
+
// W-10029836 - In the case where we could be instantiating multiple graphs at the same time lets make sure the module have not already been evaluated
|
|
1179
|
+
if (moduleRecord.evaluated) {
|
|
1180
|
+
return moduleRecord.module;
|
|
1181
|
+
}
|
|
1166
1182
|
|
|
1167
1183
|
// evaluates the module function
|
|
1168
|
-
let moduleDefault
|
|
1184
|
+
let moduleDefault;
|
|
1185
|
+
try {
|
|
1186
|
+
moduleDefault = exporter(...depsMapped);
|
|
1187
|
+
} catch (e) {
|
|
1188
|
+
throw new LoaderError(EXPORTER_ERROR, [moduleRecord.id, e.message || e]);
|
|
1189
|
+
}
|
|
1169
1190
|
// value is returned from exporter, then we are not using named exports
|
|
1170
1191
|
if (moduleDefault !== undefined) {
|
|
1171
1192
|
moduleDefault = { default: moduleDefault };
|
|
@@ -1177,7 +1198,7 @@ class ModuleRegistry {
|
|
|
1177
1198
|
// if no return value, then we are using the exports object
|
|
1178
1199
|
else {
|
|
1179
1200
|
// handle only default export with Rollup forced named exports
|
|
1180
|
-
if (isNamedExportDefaultOnly(exports)) {
|
|
1201
|
+
if (this.isNamedExportDefaultOnly(exports)) {
|
|
1181
1202
|
Object.defineProperty(exports, '__useDefault', { value: true });
|
|
1182
1203
|
}
|
|
1183
1204
|
}
|
|
@@ -1209,17 +1230,42 @@ class ModuleRegistry {
|
|
|
1209
1230
|
Object.defineProperty(moduleRecord.module, '__esModule', { value: true });
|
|
1210
1231
|
}
|
|
1211
1232
|
|
|
1212
|
-
Object.freeze(moduleRecord.module);
|
|
1213
1233
|
moduleRecord.evaluated = true;
|
|
1214
|
-
moduleRecord.
|
|
1234
|
+
Object.freeze(moduleRecord.module);
|
|
1215
1235
|
return moduleRecord.module;
|
|
1216
1236
|
}
|
|
1217
1237
|
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1238
|
+
// Determines if named exports module has only default export
|
|
1239
|
+
isNamedExportDefaultOnly(exports) {
|
|
1240
|
+
return (
|
|
1241
|
+
exports !== undefined &&
|
|
1242
|
+
Object.getOwnPropertyNames(exports).length === 2 &&
|
|
1243
|
+
Object.prototype.hasOwnProperty.call(exports, 'default') &&
|
|
1244
|
+
Object.prototype.hasOwnProperty.call(exports, '__esModule')
|
|
1245
|
+
);
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
// Wrap the dependency in a function that can be called and detected by __circular__ property.
|
|
1249
|
+
// The LWC engine checks for __circular__ to detect circular dependencies.
|
|
1250
|
+
getCircularDependencyWrapper(module) {
|
|
1251
|
+
const tmp = () => {
|
|
1252
|
+
return module.__useDefault || module.__defaultInterop ? module.default : module;
|
|
1253
|
+
};
|
|
1254
|
+
tmp.__circular__ = true;
|
|
1255
|
+
return tmp;
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1258
|
+
async evaluateModuleDependencies(
|
|
1259
|
+
dependencyModuleRecords,
|
|
1260
|
+
evaluationMap,
|
|
1261
|
+
) {
|
|
1262
|
+
for (let i = 0; i < dependencyModuleRecords.length; i++) {
|
|
1263
|
+
const depRecord = dependencyModuleRecords[i];
|
|
1264
|
+
if (!depRecord.evaluated && !evaluationMap[depRecord.id]) {
|
|
1265
|
+
evaluationMap[depRecord.id] = true;
|
|
1266
|
+
// eslint-disable-next-line no-await-in-loop
|
|
1267
|
+
await this.evaluateModule(depRecord, evaluationMap);
|
|
1268
|
+
}
|
|
1223
1269
|
}
|
|
1224
1270
|
}
|
|
1225
1271
|
|
|
@@ -1231,8 +1277,8 @@ class ModuleRegistry {
|
|
|
1231
1277
|
const moduleName = !isUrl(resolvedId)
|
|
1232
1278
|
? resolvedId
|
|
1233
1279
|
: originalId !== resolvedId
|
|
1234
|
-
|
|
1235
|
-
|
|
1280
|
+
? originalId
|
|
1281
|
+
: undefined;
|
|
1236
1282
|
let moduleDef = moduleName && this.namedDefineRegistry.get(moduleName);
|
|
1237
1283
|
if (moduleDef && moduleDef.external) {
|
|
1238
1284
|
return moduleDef.external.moduleDefPromise;
|
|
@@ -1299,6 +1345,9 @@ class ModuleRegistry {
|
|
|
1299
1345
|
});
|
|
1300
1346
|
}
|
|
1301
1347
|
|
|
1348
|
+
|
|
1349
|
+
|
|
1350
|
+
|
|
1302
1351
|
addLoaderPlugin(hooks) {
|
|
1303
1352
|
if (typeof hooks !== 'object') {
|
|
1304
1353
|
throw new LoaderError(INVALID_HOOK);
|
|
@@ -1340,6 +1389,7 @@ class ModuleRegistry {
|
|
|
1340
1389
|
}
|
|
1341
1390
|
}
|
|
1342
1391
|
|
|
1392
|
+
|
|
1343
1393
|
registerHandleStaleModuleHook(handleStaleModule) {
|
|
1344
1394
|
if (this.handleStaleModuleHook) {
|
|
1345
1395
|
this.handleStaleModuleHook.push(handleStaleModule);
|
|
@@ -1347,30 +1397,12 @@ class ModuleRegistry {
|
|
|
1347
1397
|
this.handleStaleModuleHook = [handleStaleModule];
|
|
1348
1398
|
}
|
|
1349
1399
|
}
|
|
1350
|
-
}
|
|
1351
1400
|
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
Object.prototype.hasOwnProperty.call(exports, 'default') &&
|
|
1358
|
-
Object.prototype.hasOwnProperty.call(exports, '__esModule')
|
|
1359
|
-
);
|
|
1360
|
-
}
|
|
1361
|
-
|
|
1362
|
-
// Wrap the dependency in a function that can be called and detected by __circular__ property.
|
|
1363
|
-
// The LWC engine checks for __circular__ to detect circular dependencies.
|
|
1364
|
-
function getCircularDependencyWrapper(module) {
|
|
1365
|
-
const tmp = () => {
|
|
1366
|
-
return module.__useDefault || module.__defaultInterop ? module.default : module;
|
|
1367
|
-
};
|
|
1368
|
-
tmp.__circular__ = true;
|
|
1369
|
-
return tmp;
|
|
1370
|
-
}
|
|
1371
|
-
|
|
1372
|
-
function isValidResolveResponse(res) {
|
|
1373
|
-
return res === null || typeof res === 'string' || (res && typeof (res ).url === 'string');
|
|
1401
|
+
isValidResolveResponse(res) {
|
|
1402
|
+
return (
|
|
1403
|
+
res === null || typeof res === 'string' || (res && typeof (res ).url === 'string')
|
|
1404
|
+
);
|
|
1405
|
+
}
|
|
1374
1406
|
}
|
|
1375
1407
|
|
|
1376
1408
|
/**
|