@cesium/engine 2.2.0 → 2.4.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.
Files changed (139) hide show
  1. package/Build/Workers/{AttributeCompression-8a5a065e.js → AttributeCompression-f9f6c717.js} +1 -1
  2. package/Build/Workers/{AxisAlignedBoundingBox-379015ef.js → AxisAlignedBoundingBox-4bfd84f3.js} +1 -1
  3. package/Build/Workers/{BoundingRectangle-57f2b24f.js → BoundingRectangle-5fd6403a.js} +1 -1
  4. package/Build/Workers/{BoxGeometry-ecabfc78.js → BoxGeometry-af7d05ef.js} +1 -1
  5. package/Build/Workers/{Color-14d1a36d.js → Color-e5bfda3f.js} +1 -1
  6. package/Build/Workers/{CoplanarPolygonGeometryLibrary-048c3c14.js → CoplanarPolygonGeometryLibrary-59c69b0a.js} +1 -1
  7. package/Build/Workers/{CorridorGeometryLibrary-520c8619.js → CorridorGeometryLibrary-63907365.js} +1 -1
  8. package/Build/Workers/{CylinderGeometry-119068b8.js → CylinderGeometry-dbaa1678.js} +1 -1
  9. package/Build/Workers/{CylinderGeometryLibrary-135b0858.js → CylinderGeometryLibrary-7bf291b4.js} +1 -1
  10. package/Build/Workers/{EllipseGeometry-2dfc3523.js → EllipseGeometry-6508b78b.js} +1 -1
  11. package/Build/Workers/{EllipseGeometryLibrary-0a1e0170.js → EllipseGeometryLibrary-21262a28.js} +1 -1
  12. package/Build/Workers/{EllipseOutlineGeometry-c5251669.js → EllipseOutlineGeometry-2a2510bb.js} +1 -1
  13. package/Build/Workers/{EllipsoidGeodesic-dcff5cbd.js → EllipsoidGeodesic-5b3623dc.js} +1 -1
  14. package/Build/Workers/{EllipsoidGeometry-d10a5221.js → EllipsoidGeometry-8155e3a2.js} +1 -1
  15. package/Build/Workers/{EllipsoidOutlineGeometry-7039a0ae.js → EllipsoidOutlineGeometry-c045678d.js} +1 -1
  16. package/Build/Workers/{EllipsoidRhumbLine-b672d507.js → EllipsoidRhumbLine-ef872433.js} +1 -1
  17. package/Build/Workers/{EllipsoidTangentPlane-857186be.js → EllipsoidTangentPlane-546c0d5e.js} +1 -1
  18. package/Build/Workers/{EncodedCartesian3-e8bbca36.js → EncodedCartesian3-57415c8a.js} +1 -1
  19. package/Build/Workers/{FrustumGeometry-400fa1b7.js → FrustumGeometry-d3ff16d0.js} +31 -3
  20. package/Build/Workers/{GeometryAttribute-7a2de5c6.js → GeometryAttribute-13da9466.js} +1 -1
  21. package/Build/Workers/{GeometryInstance-3fb607b7.js → GeometryInstance-34d9e21e.js} +1 -1
  22. package/Build/Workers/{GeometryPipeline-916636fa.js → GeometryPipeline-03bc5709.js} +1 -1
  23. package/Build/Workers/{IndexDatatype-b8f3e09d.js → IndexDatatype-2643aa47.js} +1 -1
  24. package/Build/Workers/{IntersectionTests-b4d02d4d.js → IntersectionTests-85350792.js} +1 -1
  25. package/Build/Workers/{Math-dad82b4d.js → Math-0a2ac845.js} +12 -2
  26. package/Build/Workers/{Matrix2-1e403d0e.js → Matrix2-e1298525.js} +1 -1
  27. package/Build/Workers/{Matrix3-fa806b97.js → Matrix3-41c58dde.js} +1 -1
  28. package/Build/Workers/{OrientedBoundingBox-96fe1752.js → OrientedBoundingBox-29fb0fcd.js} +1 -1
  29. package/Build/Workers/{Plane-c27e1ac6.js → Plane-4c3d403b.js} +1 -1
  30. package/Build/Workers/{PolygonGeometryLibrary-931f1ec6.js → PolygonGeometryLibrary-d447448d.js} +1 -1
  31. package/Build/Workers/PolygonPipeline-460cce4e.js +1344 -0
  32. package/Build/Workers/{PolylinePipeline-6d5c63e5.js → PolylinePipeline-7119eb3f.js} +1 -1
  33. package/Build/Workers/{PolylineVolumeGeometryLibrary-f068c1fb.js → PolylineVolumeGeometryLibrary-d25f0050.js} +1 -1
  34. package/Build/Workers/{PrimitivePipeline-879f996a.js → PrimitivePipeline-e648752b.js} +1 -1
  35. package/Build/Workers/{RectangleGeometryLibrary-2d6f36f3.js → RectangleGeometryLibrary-bb378fb6.js} +1 -1
  36. package/Build/Workers/{TerrainEncoding-82882059.js → TerrainEncoding-c8e029a2.js} +1 -1
  37. package/Build/Workers/Transforms-e2d4a55a.js +14713 -0
  38. package/Build/Workers/{WallGeometryLibrary-db7a64fb.js → WallGeometryLibrary-3e0819ec.js} +1 -1
  39. package/Build/Workers/{WebMercatorProjection-76a3fcc0.js → WebMercatorProjection-13ed1a6e.js} +1 -1
  40. package/Build/Workers/{arrayRemoveDuplicates-fac118a8.js → arrayRemoveDuplicates-d2061e85.js} +1 -1
  41. package/Build/Workers/cesiumWorkerBootstrapper.js +1 -1
  42. package/Build/Workers/combineGeometry.js +1 -1
  43. package/Build/Workers/createBoxGeometry.js +1 -1
  44. package/Build/Workers/createBoxOutlineGeometry.js +1 -1
  45. package/Build/Workers/createCircleGeometry.js +1 -1
  46. package/Build/Workers/createCircleOutlineGeometry.js +1 -1
  47. package/Build/Workers/createCoplanarPolygonGeometry.js +1 -1
  48. package/Build/Workers/createCoplanarPolygonOutlineGeometry.js +1 -1
  49. package/Build/Workers/createCorridorGeometry.js +1 -1
  50. package/Build/Workers/createCorridorOutlineGeometry.js +1 -1
  51. package/Build/Workers/createCylinderGeometry.js +1 -1
  52. package/Build/Workers/createCylinderOutlineGeometry.js +1 -1
  53. package/Build/Workers/createEllipseGeometry.js +1 -1
  54. package/Build/Workers/createEllipseOutlineGeometry.js +1 -1
  55. package/Build/Workers/createEllipsoidGeometry.js +1 -1
  56. package/Build/Workers/createEllipsoidOutlineGeometry.js +1 -1
  57. package/Build/Workers/createFrustumGeometry.js +1 -1
  58. package/Build/Workers/createFrustumOutlineGeometry.js +1 -1
  59. package/Build/Workers/createGeometry.js +1 -1
  60. package/Build/Workers/createGroundPolylineGeometry.js +1 -1
  61. package/Build/Workers/createPlaneGeometry.js +1 -1
  62. package/Build/Workers/createPlaneOutlineGeometry.js +1 -1
  63. package/Build/Workers/createPolygonGeometry.js +1 -1
  64. package/Build/Workers/createPolygonOutlineGeometry.js +1 -1
  65. package/Build/Workers/createPolylineGeometry.js +1 -1
  66. package/Build/Workers/createPolylineVolumeGeometry.js +1 -1
  67. package/Build/Workers/createPolylineVolumeOutlineGeometry.js +1 -1
  68. package/Build/Workers/createRectangleGeometry.js +1 -1
  69. package/Build/Workers/createRectangleOutlineGeometry.js +1 -1
  70. package/Build/Workers/createSimplePolylineGeometry.js +1 -1
  71. package/Build/Workers/createSphereGeometry.js +1 -1
  72. package/Build/Workers/createSphereOutlineGeometry.js +1 -1
  73. package/Build/Workers/createVectorTileClampedPolylines.js +1 -1
  74. package/Build/Workers/createVectorTileGeometries.js +1 -1
  75. package/Build/Workers/createVectorTilePoints.js +1 -1
  76. package/Build/Workers/createVectorTilePolygons.js +1 -1
  77. package/Build/Workers/createVectorTilePolylines.js +1 -1
  78. package/Build/Workers/createVerticesFromGoogleEarthEnterpriseBuffer.js +1 -1
  79. package/Build/Workers/createVerticesFromHeightmap.js +5 -8
  80. package/Build/Workers/createVerticesFromQuantizedTerrainMesh.js +1 -1
  81. package/Build/Workers/createWallGeometry.js +1 -1
  82. package/Build/Workers/createWallOutlineGeometry.js +1 -1
  83. package/Build/Workers/decodeDraco.js +1 -1
  84. package/Build/Workers/decodeI3S.js +1 -1
  85. package/Build/Workers/package.js +1 -1
  86. package/Build/Workers/transferTypedArrayTest.js +1 -1
  87. package/Build/Workers/upsampleQuantizedTerrainMesh.js +1 -1
  88. package/Source/Core/BingMapsGeocoderService.js +19 -1
  89. package/Source/Core/CartographicGeocoderService.js +15 -0
  90. package/Source/Core/Credit.js +1 -1
  91. package/Source/Core/FrustumGeometry.js +3 -2
  92. package/Source/Core/GeocoderService.js +32 -1
  93. package/Source/Core/GoogleMaps.js +56 -0
  94. package/Source/Core/Ion.js +2 -1
  95. package/Source/Core/IonGeocoderService.js +17 -2
  96. package/Source/Core/OpenCageGeocoderService.js +18 -1
  97. package/Source/Core/OrthographicFrustum.js +13 -0
  98. package/Source/Core/PeliasGeocoderService.js +14 -1
  99. package/Source/Core/PerspectiveFrustum.js +14 -0
  100. package/Source/Core/Request.js +3 -2
  101. package/Source/Core/RequestScheduler.js +10 -4
  102. package/Source/Core/Resource.js +240 -233
  103. package/Source/DataSources/DataSourceDisplay.js +2 -2
  104. package/Source/DataSources/EntityCluster.js +126 -128
  105. package/Source/DataSources/ModelVisualizer.js +5 -3
  106. package/Source/Renderer/UniformState.js +3 -2
  107. package/Source/Renderer/demodernizeShader.js +5 -5
  108. package/Source/Scene/ArcGisBaseMapType.js +12 -0
  109. package/Source/Scene/ArcGisMapServerImageryProvider.js +162 -20
  110. package/Source/Scene/ArcGisMapService.js +84 -0
  111. package/Source/Scene/Camera.js +8 -7
  112. package/Source/Scene/Cesium3DTile.js +4 -3
  113. package/Source/Scene/Cesium3DTileset.js +6 -5
  114. package/Source/Scene/CreditDisplay.js +112 -16
  115. package/Source/Scene/GlobeSurfaceTileProvider.js +4 -4
  116. package/Source/Scene/GltfJsonLoader.js +12 -0
  117. package/Source/Scene/GltfLoader.js +6 -37
  118. package/Source/Scene/IonImageryProvider.js +11 -11
  119. package/Source/Scene/Model/MaterialPipelineStage.js +12 -12
  120. package/Source/Scene/Model/Model.js +90 -47
  121. package/Source/Scene/Model/UniformType.js +1 -1
  122. package/Source/Scene/Picking.js +3 -2
  123. package/Source/Scene/QuadtreePrimitive.js +3 -2
  124. package/Source/Scene/SceneTransforms.js +3 -2
  125. package/Source/Scene/ScreenSpaceCameraController.js +140 -32
  126. package/Source/Scene/Vector3DTilePoints.js +25 -13
  127. package/Source/Scene/createGooglePhotorealistic3DTileset.js +53 -0
  128. package/Source/Shaders/AtmosphereCommon.glsl +51 -8
  129. package/Source/Shaders/AtmosphereCommon.js +51 -8
  130. package/Source/Shaders/PostProcessStages/AmbientOcclusionGenerate.glsl +1 -1
  131. package/Source/Shaders/PostProcessStages/AmbientOcclusionGenerate.js +1 -1
  132. package/Source/Shaders/PostProcessStages/AmbientOcclusionModulate.glsl +3 -3
  133. package/Source/Shaders/PostProcessStages/AmbientOcclusionModulate.js +3 -3
  134. package/Source/Widget/CesiumWidget.js +12 -0
  135. package/index.d.ts +244 -17
  136. package/index.js +14 -10
  137. package/package.json +4 -4
  138. package/Build/Workers/PolygonPipeline-32fc92cc.js +0 -1345
  139. package/Build/Workers/Transforms-9052372a.js +0 -14715
@@ -36,184 +36,6 @@ const xhrBlobSupported = (function () {
36
36
  }
37
37
  })();
38
38
 
39
- /**
40
- * Parses a query string and returns the object equivalent.
41
- *
42
- * @param {Uri} uri The Uri with a query object.
43
- * @param {Resource} resource The Resource that will be assigned queryParameters.
44
- * @param {boolean} merge If true, we'll merge with the resource's existing queryParameters. Otherwise they will be replaced.
45
- * @param {boolean} preserveQueryParameters If true duplicate parameters will be concatenated into an array. If false, keys in uri will take precedence.
46
- *
47
- * @private
48
- */
49
- function parseQuery(uri, resource, merge, preserveQueryParameters) {
50
- const queryString = uri.query();
51
- if (queryString.length === 0) {
52
- return {};
53
- }
54
-
55
- let query;
56
- // Special case we run into where the querystring is just a string, not key/value pairs
57
- if (queryString.indexOf("=") === -1) {
58
- const result = {};
59
- result[queryString] = undefined;
60
- query = result;
61
- } else {
62
- query = queryToObject(queryString);
63
- }
64
-
65
- if (merge) {
66
- resource._queryParameters = combineQueryParameters(
67
- query,
68
- resource._queryParameters,
69
- preserveQueryParameters
70
- );
71
- } else {
72
- resource._queryParameters = query;
73
- }
74
- uri.search("");
75
- }
76
-
77
- /**
78
- * Converts a query object into a string.
79
- *
80
- * @param {Uri} uri The Uri object that will have the query object set.
81
- * @param {Resource} resource The resource that has queryParameters
82
- *
83
- * @private
84
- */
85
- function stringifyQuery(uri, resource) {
86
- const queryObject = resource._queryParameters;
87
-
88
- const keys = Object.keys(queryObject);
89
-
90
- // We have 1 key with an undefined value, so this is just a string, not key/value pairs
91
- if (keys.length === 1 && !defined(queryObject[keys[0]])) {
92
- uri.search(keys[0]);
93
- } else {
94
- uri.search(objectToQuery(queryObject));
95
- }
96
- }
97
-
98
- /**
99
- * Clones a value if it is defined, otherwise returns the default value
100
- *
101
- * @param {*} [val] The value to clone.
102
- * @param {*} [defaultVal] The default value.
103
- *
104
- * @returns {*} A clone of val or the defaultVal.
105
- *
106
- * @private
107
- */
108
- function defaultClone(val, defaultVal) {
109
- if (!defined(val)) {
110
- return defaultVal;
111
- }
112
-
113
- return defined(val.clone) ? val.clone() : clone(val);
114
- }
115
-
116
- /**
117
- * Checks to make sure the Resource isn't already being requested.
118
- *
119
- * @param {Request} request The request to check.
120
- *
121
- * @private
122
- */
123
- function checkAndResetRequest(request) {
124
- if (
125
- request.state === RequestState.ISSUED ||
126
- request.state === RequestState.ACTIVE
127
- ) {
128
- throw new RuntimeError("The Resource is already being fetched.");
129
- }
130
-
131
- request.state = RequestState.UNISSUED;
132
- request.deferred = undefined;
133
- }
134
-
135
- /**
136
- * This combines a map of query parameters.
137
- *
138
- * @param {object} q1 The first map of query parameters. Values in this map will take precedence if preserveQueryParameters is false.
139
- * @param {object} q2 The second map of query parameters.
140
- * @param {boolean} preserveQueryParameters If true duplicate parameters will be concatenated into an array. If false, keys in q1 will take precedence.
141
- *
142
- * @returns {object} The combined map of query parameters.
143
- *
144
- * @example
145
- * const q1 = {
146
- * a: 1,
147
- * b: 2
148
- * };
149
- * const q2 = {
150
- * a: 3,
151
- * c: 4
152
- * };
153
- * const q3 = {
154
- * b: [5, 6],
155
- * d: 7
156
- * }
157
- *
158
- * // Returns
159
- * // {
160
- * // a: [1, 3],
161
- * // b: 2,
162
- * // c: 4
163
- * // };
164
- * combineQueryParameters(q1, q2, true);
165
- *
166
- * // Returns
167
- * // {
168
- * // a: 1,
169
- * // b: 2,
170
- * // c: 4
171
- * // };
172
- * combineQueryParameters(q1, q2, false);
173
- *
174
- * // Returns
175
- * // {
176
- * // a: 1,
177
- * // b: [2, 5, 6],
178
- * // d: 7
179
- * // };
180
- * combineQueryParameters(q1, q3, true);
181
- *
182
- * // Returns
183
- * // {
184
- * // a: 1,
185
- * // b: 2,
186
- * // d: 7
187
- * // };
188
- * combineQueryParameters(q1, q3, false);
189
- *
190
- * @private
191
- */
192
- function combineQueryParameters(q1, q2, preserveQueryParameters) {
193
- if (!preserveQueryParameters) {
194
- return combine(q1, q2);
195
- }
196
-
197
- const result = clone(q1, true);
198
- for (const param in q2) {
199
- if (q2.hasOwnProperty(param)) {
200
- let value = result[param];
201
- const q2Value = q2[param];
202
- if (defined(value)) {
203
- if (!Array.isArray(value)) {
204
- value = result[param] = [value];
205
- }
206
-
207
- result[param] = value.concat(q2Value);
208
- } else {
209
- result[param] = Array.isArray(q2Value) ? q2Value.slice() : q2Value;
210
- }
211
- }
212
- }
213
-
214
- return result;
215
- }
216
-
217
39
  /**
218
40
  * @typedef {object} Resource.ConstructorOptions
219
41
  *
@@ -227,6 +49,7 @@ function combineQueryParameters(q1, q2, preserveQueryParameters) {
227
49
  * @property {Resource.RetryCallback} [retryCallback] The Function to call when a request for this resource fails. If it returns true, the request will be retried.
228
50
  * @property {number} [retryAttempts=0] The number of times the retryCallback should be called before giving up.
229
51
  * @property {Request} [request] A Request object that will be used. Intended for internal use only.
52
+ * @property {boolean} [parseUrl=true] If true, parse the url for query parameters; otherwise store the url without change
230
53
  */
231
54
 
232
55
  /**
@@ -319,13 +142,28 @@ function Resource(options) {
319
142
  this.retryAttempts = defaultValue(options.retryAttempts, 0);
320
143
  this._retryCount = 0;
321
144
 
322
- const uri = new Uri(options.url);
323
- parseQuery(uri, this, true, true);
145
+ const parseUrl = defaultValue(options.parseUrl, true);
146
+ if (parseUrl) {
147
+ this.parseUrl(options.url, true, true);
148
+ } else {
149
+ this._url = options.url;
150
+ }
324
151
 
325
- // Remove the fragment as it's not sent with a request
326
- uri.fragment("");
152
+ this._credits = options.credits;
153
+ }
327
154
 
328
- this._url = uri.toString();
155
+ /**
156
+ * Clones a value if it is defined, otherwise returns the default value
157
+ *
158
+ * @param {object} [value] The value to clone.
159
+ * @param {object} [defaultValue] The default value.
160
+ *
161
+ * @returns {object} A clone of value or the defaultValue.
162
+ *
163
+ * @private
164
+ */
165
+ function defaultClone(value, defaultValue) {
166
+ return defined(value) ? clone(value) : defaultValue;
329
167
  }
330
168
 
331
169
  /**
@@ -471,14 +309,7 @@ Object.defineProperties(Resource.prototype, {
471
309
  return this.getUrlComponent(true, true);
472
310
  },
473
311
  set: function (value) {
474
- const uri = new Uri(value);
475
-
476
- parseQuery(uri, this, false);
477
-
478
- // Remove the fragment as it's not sent with a request
479
- uri.fragment("");
480
-
481
- this._url = uri.toString();
312
+ this.parseUrl(value, false, false);
482
313
  },
483
314
  },
484
315
 
@@ -543,6 +374,16 @@ Object.defineProperties(Resource.prototype, {
543
374
  return Object.keys(this.headers).length > 0;
544
375
  },
545
376
  },
377
+
378
+ /**
379
+ * Gets the credits required for attribution of an asset.
380
+ * @private
381
+ */
382
+ credits: {
383
+ get: function () {
384
+ return this._credits;
385
+ },
386
+ },
546
387
  });
547
388
 
548
389
  /**
@@ -555,6 +396,138 @@ Resource.prototype.toString = function () {
555
396
  return this.getUrlComponent(true, true);
556
397
  };
557
398
 
399
+ /**
400
+ * Parse a url string, and store its info
401
+ *
402
+ * @param {string} url The input url string.
403
+ * @param {boolean} merge If true, we'll merge with the resource's existing queryParameters. Otherwise they will be replaced.
404
+ * @param {boolean} preserveQuery If true duplicate parameters will be concatenated into an array. If false, keys in url will take precedence.
405
+ * @param {string} [baseUrl] If supplied, and input url is a relative url, it will be made absolute relative to baseUrl
406
+ *
407
+ * @private
408
+ */
409
+ Resource.prototype.parseUrl = function (url, merge, preserveQuery, baseUrl) {
410
+ let uri = new Uri(url);
411
+ const query = parseQueryString(uri.query());
412
+
413
+ this._queryParameters = merge
414
+ ? combineQueryParameters(query, this.queryParameters, preserveQuery)
415
+ : query;
416
+
417
+ // Remove unneeded info from the Uri
418
+ uri.search("");
419
+ uri.fragment("");
420
+
421
+ if (defined(baseUrl) && uri.scheme() === "") {
422
+ uri = uri.absoluteTo(getAbsoluteUri(baseUrl));
423
+ }
424
+
425
+ this._url = uri.toString();
426
+ };
427
+
428
+ /**
429
+ * Parses a query string and returns the object equivalent.
430
+ *
431
+ * @param {string} queryString The query string
432
+ * @returns {object}
433
+ *
434
+ * @private
435
+ */
436
+ function parseQueryString(queryString) {
437
+ if (queryString.length === 0) {
438
+ return {};
439
+ }
440
+
441
+ // Special case where the querystring is just a string, not key/value pairs
442
+ if (queryString.indexOf("=") === -1) {
443
+ return { [queryString]: undefined };
444
+ }
445
+
446
+ return queryToObject(queryString);
447
+ }
448
+
449
+ /**
450
+ * This combines a map of query parameters.
451
+ *
452
+ * @param {object} q1 The first map of query parameters. Values in this map will take precedence if preserveQueryParameters is false.
453
+ * @param {object} q2 The second map of query parameters.
454
+ * @param {boolean} preserveQueryParameters If true duplicate parameters will be concatenated into an array. If false, keys in q1 will take precedence.
455
+ *
456
+ * @returns {object} The combined map of query parameters.
457
+ *
458
+ * @example
459
+ * const q1 = {
460
+ * a: 1,
461
+ * b: 2
462
+ * };
463
+ * const q2 = {
464
+ * a: 3,
465
+ * c: 4
466
+ * };
467
+ * const q3 = {
468
+ * b: [5, 6],
469
+ * d: 7
470
+ * }
471
+ *
472
+ * // Returns
473
+ * // {
474
+ * // a: [1, 3],
475
+ * // b: 2,
476
+ * // c: 4
477
+ * // };
478
+ * combineQueryParameters(q1, q2, true);
479
+ *
480
+ * // Returns
481
+ * // {
482
+ * // a: 1,
483
+ * // b: 2,
484
+ * // c: 4
485
+ * // };
486
+ * combineQueryParameters(q1, q2, false);
487
+ *
488
+ * // Returns
489
+ * // {
490
+ * // a: 1,
491
+ * // b: [2, 5, 6],
492
+ * // d: 7
493
+ * // };
494
+ * combineQueryParameters(q1, q3, true);
495
+ *
496
+ * // Returns
497
+ * // {
498
+ * // a: 1,
499
+ * // b: 2,
500
+ * // d: 7
501
+ * // };
502
+ * combineQueryParameters(q1, q3, false);
503
+ *
504
+ * @private
505
+ */
506
+ function combineQueryParameters(q1, q2, preserveQueryParameters) {
507
+ if (!preserveQueryParameters) {
508
+ return combine(q1, q2);
509
+ }
510
+
511
+ const result = clone(q1, true);
512
+ for (const param in q2) {
513
+ if (q2.hasOwnProperty(param)) {
514
+ let value = result[param];
515
+ const q2Value = q2[param];
516
+ if (defined(value)) {
517
+ if (!Array.isArray(value)) {
518
+ value = result[param] = [value];
519
+ }
520
+
521
+ result[param] = value.concat(q2Value);
522
+ } else {
523
+ result[param] = Array.isArray(q2Value) ? q2Value.slice() : q2Value;
524
+ }
525
+ }
526
+ }
527
+
528
+ return result;
529
+ }
530
+
558
531
  /**
559
532
  * Returns the url, optional with the query string and processed by a proxy.
560
533
  *
@@ -568,32 +541,56 @@ Resource.prototype.getUrlComponent = function (query, proxy) {
568
541
  return this._url;
569
542
  }
570
543
 
571
- const uri = new Uri(this._url);
572
-
544
+ let url = this._url;
573
545
  if (query) {
574
- stringifyQuery(uri, this);
546
+ url = `${url}${stringifyQuery(this.queryParameters)}`;
575
547
  }
576
548
 
577
- // objectToQuery escapes the placeholders. Undo that.
578
- let url = uri.toString().replace(/%7B/g, "{").replace(/%7D/g, "}");
549
+ // Restore the placeholders, which may have been escaped in objectToQuery or elsewhere
550
+ url = url.replace(/%7B/g, "{").replace(/%7D/g, "}");
579
551
 
580
552
  const templateValues = this._templateValues;
581
- url = url.replace(/{(.*?)}/g, function (match, key) {
582
- const replacement = templateValues[key];
583
- if (defined(replacement)) {
584
- // use the replacement value from templateValues if there is one...
585
- return encodeURIComponent(replacement);
586
- }
587
- // otherwise leave it unchanged
588
- return match;
589
- });
553
+ if (Object.keys(templateValues).length > 0) {
554
+ url = url.replace(/{(.*?)}/g, function (match, key) {
555
+ const replacement = templateValues[key];
556
+ if (defined(replacement)) {
557
+ // use the replacement value from templateValues if there is one...
558
+ return encodeURIComponent(replacement);
559
+ }
560
+ // otherwise leave it unchanged
561
+ return match;
562
+ });
563
+ }
590
564
 
591
565
  if (proxy && defined(this.proxy)) {
592
566
  url = this.proxy.getURL(url);
593
567
  }
568
+
594
569
  return url;
595
570
  };
596
571
 
572
+ /**
573
+ * Converts a query object into a string.
574
+ *
575
+ * @param {object} queryObject The object with query parameters
576
+ * @returns {string}
577
+ *
578
+ * @private
579
+ */
580
+ function stringifyQuery(queryObject) {
581
+ const keys = Object.keys(queryObject);
582
+
583
+ if (keys.length === 0) {
584
+ return "";
585
+ }
586
+ if (keys.length === 1 && !defined(queryObject[keys[0]])) {
587
+ // We have 1 key with an undefined value, so this is just a string, not key/value pairs
588
+ return `?${keys[0]}`;
589
+ }
590
+
591
+ return `?${objectToQuery(queryObject)}`;
592
+ }
593
+
597
594
  /**
598
595
  * Combines the specified object and the existing query parameters. This allows you to add many parameters at once,
599
596
  * as opposed to adding them one at a time to the queryParameters property. If a value is already set, it will be replaced with the new value.
@@ -667,30 +664,14 @@ Resource.prototype.getDerivedResource = function (options) {
667
664
  resource._retryCount = 0;
668
665
 
669
666
  if (defined(options.url)) {
670
- const uri = new Uri(options.url);
671
-
672
- const preserveQueryParameters = defaultValue(
673
- options.preserveQueryParameters,
674
- false
675
- );
676
- parseQuery(uri, resource, true, preserveQueryParameters);
677
-
678
- // Remove the fragment as it's not sent with a request
679
- uri.fragment("");
680
-
681
- if (uri.scheme() !== "") {
682
- resource._url = uri.toString();
683
- } else {
684
- resource._url = uri
685
- .absoluteTo(new Uri(getAbsoluteUri(this._url)))
686
- .toString();
687
- }
667
+ const preserveQuery = defaultValue(options.preserveQueryParameters, false);
668
+ resource.parseUrl(options.url, true, preserveQuery, this._url);
688
669
  }
689
670
 
690
671
  if (defined(options.queryParameters)) {
691
672
  resource._queryParameters = combine(
692
673
  options.queryParameters,
693
- resource._queryParameters
674
+ resource.queryParameters
694
675
  );
695
676
  }
696
677
  if (defined(options.templateValues)) {
@@ -753,8 +734,17 @@ Resource.prototype.retryOnError = function (error) {
753
734
  */
754
735
  Resource.prototype.clone = function (result) {
755
736
  if (!defined(result)) {
756
- result = new Resource({
737
+ return new Resource({
757
738
  url: this._url,
739
+ queryParameters: this.queryParameters,
740
+ templateValues: this.templateValues,
741
+ headers: this.headers,
742
+ proxy: this.proxy,
743
+ retryCallback: this.retryCallback,
744
+ retryAttempts: this.retryAttempts,
745
+ request: this.request.clone(),
746
+ parseUrl: false,
747
+ credits: defined(this.credits) ? this.credits.slice() : undefined,
758
748
  });
759
749
  }
760
750
 
@@ -1301,7 +1291,8 @@ function fetchJsonp(resource, callbackParameterName, functionName) {
1301
1291
  resource.setQueryParameters(callbackQuery);
1302
1292
 
1303
1293
  const request = resource.request;
1304
- request.url = resource.url;
1294
+ const url = resource.url;
1295
+ request.url = url;
1305
1296
  request.requestFunction = function () {
1306
1297
  const deferred = defer();
1307
1298
 
@@ -1316,11 +1307,7 @@ function fetchJsonp(resource, callbackParameterName, functionName) {
1316
1307
  }
1317
1308
  };
1318
1309
 
1319
- Resource._Implementations.loadAndExecuteScript(
1320
- resource.url,
1321
- functionName,
1322
- deferred
1323
- );
1310
+ Resource._Implementations.loadAndExecuteScript(url, functionName, deferred);
1324
1311
  return deferred.promise;
1325
1312
  };
1326
1313
 
@@ -1376,7 +1363,8 @@ Resource.prototype._makeRequest = function (options) {
1376
1363
  checkAndResetRequest(resource.request);
1377
1364
 
1378
1365
  const request = resource.request;
1379
- request.url = resource.url;
1366
+ const url = resource.url;
1367
+ request.url = url;
1380
1368
 
1381
1369
  request.requestFunction = function () {
1382
1370
  const responseType = options.responseType;
@@ -1386,7 +1374,7 @@ Resource.prototype._makeRequest = function (options) {
1386
1374
  const data = options.data;
1387
1375
  const deferred = defer();
1388
1376
  const xhr = Resource._Implementations.loadWithXhr(
1389
- resource.url,
1377
+ url,
1390
1378
  responseType,
1391
1379
  method,
1392
1380
  data,
@@ -1433,6 +1421,25 @@ Resource.prototype._makeRequest = function (options) {
1433
1421
  });
1434
1422
  };
1435
1423
 
1424
+ /**
1425
+ * Checks to make sure the Resource isn't already being requested.
1426
+ *
1427
+ * @param {Request} request The request to check.
1428
+ *
1429
+ * @private
1430
+ */
1431
+ function checkAndResetRequest(request) {
1432
+ if (
1433
+ request.state === RequestState.ISSUED ||
1434
+ request.state === RequestState.ACTIVE
1435
+ ) {
1436
+ throw new RuntimeError("The Resource is already being fetched.");
1437
+ }
1438
+
1439
+ request.state = RequestState.UNISSUED;
1440
+ request.deferred = undefined;
1441
+ }
1442
+
1436
1443
  const dataUriRegex = /^data:(.*?)(;base64)?,(.*)$/;
1437
1444
 
1438
1445
  function decodeDataUriText(isBase64, data) {
@@ -313,7 +313,7 @@ DataSourceDisplay.prototype._postRender = function () {
313
313
 
314
314
  const credit = dataSource.credit;
315
315
  if (defined(credit)) {
316
- frameState.creditDisplay.addCredit(credit);
316
+ frameState.creditDisplay.addCreditToNextFrame(credit);
317
317
  }
318
318
 
319
319
  // Credits from the resource that the user can't remove
@@ -321,7 +321,7 @@ DataSourceDisplay.prototype._postRender = function () {
321
321
  if (defined(credits)) {
322
322
  const creditCount = credits.length;
323
323
  for (let c = 0; c < creditCount; c++) {
324
- frameState.creditDisplay.addCredit(credits[c]);
324
+ frameState.creditDisplay.addCreditToNextFrame(credits[c]);
325
325
  }
326
326
  }
327
327
  }