@webspatial/core-sdk 1.7.0 → 2.0.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 (296) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/README.md +10 -0
  3. package/dist/JSBCommand.d.ts +398 -0
  4. package/dist/JSBCommand.js +668 -0
  5. package/dist/JSBCommand.js.map +1 -0
  6. package/dist/Spatial.d.ts +63 -0
  7. package/dist/Spatial.js +60 -0
  8. package/dist/Spatial.js.map +1 -0
  9. package/dist/SpatialObject.d.ts +19 -0
  10. package/dist/SpatialObject.js +44 -0
  11. package/dist/SpatialObject.js.map +1 -0
  12. package/dist/SpatialScene.d.ts +51 -0
  13. package/dist/SpatialScene.js +74 -0
  14. package/dist/SpatialScene.js.map +1 -0
  15. package/dist/SpatialSession.d.ts +143 -0
  16. package/dist/SpatialSession.js +173 -0
  17. package/dist/SpatialSession.js.map +1 -0
  18. package/dist/SpatialWebEvent.d.ts +8 -0
  19. package/dist/SpatialWebEvent.js +18 -0
  20. package/dist/SpatialWebEvent.js.map +1 -0
  21. package/dist/SpatialWebEventCreator.d.ts +11 -0
  22. package/dist/SpatialWebEventCreator.js +11 -0
  23. package/dist/SpatialWebEventCreator.js.map +1 -0
  24. package/dist/Spatialized2DElement.d.ts +42 -0
  25. package/dist/Spatialized2DElement.js +47 -0
  26. package/dist/Spatialized2DElement.js.map +1 -0
  27. package/dist/SpatializedDynamic3DElement.d.ts +7 -0
  28. package/dist/SpatializedDynamic3DElement.js +43 -0
  29. package/dist/SpatializedDynamic3DElement.js.map +1 -0
  30. package/dist/SpatializedElement.d.ts +7 -0
  31. package/dist/SpatializedElement.js +206 -0
  32. package/dist/SpatializedElement.js.map +1 -0
  33. package/dist/SpatializedElementCreator.d.ts +15 -0
  34. package/dist/SpatializedElementCreator.js +47 -0
  35. package/dist/SpatializedElementCreator.js.map +1 -0
  36. package/dist/SpatializedStatic3DElement.d.ts +195 -0
  37. package/dist/SpatializedStatic3DElement.js +327 -0
  38. package/dist/SpatializedStatic3DElement.js.map +1 -0
  39. package/dist/WebMsgCommand.d.ts +7 -0
  40. package/dist/WebMsgCommand.js +23 -0
  41. package/dist/WebMsgCommand.js.map +1 -0
  42. package/dist/index.d.ts +35 -1251
  43. package/dist/index.js +21 -3650
  44. package/dist/index.js.map +1 -1
  45. package/dist/install-polyfills.d.ts +2 -0
  46. package/dist/install-polyfills.js +13 -0
  47. package/dist/install-polyfills.js.map +1 -0
  48. package/dist/isSSREnv.d.ts +3 -0
  49. package/dist/isSSREnv.js +6 -0
  50. package/dist/isSSREnv.js.map +1 -0
  51. package/dist/motion/AnimationObject.d.ts +7 -0
  52. package/dist/motion/AnimationObject.js +140 -0
  53. package/dist/motion/AnimationObject.js.map +1 -0
  54. package/dist/motion/compute/index.d.ts +10 -0
  55. package/dist/motion/compute/index.js +19 -0
  56. package/dist/motion/compute/index.js.map +1 -0
  57. package/dist/motion/compute/motionPropertyValues.d.ts +19 -0
  58. package/dist/motion/compute/motionPropertyValues.js +50 -0
  59. package/dist/motion/compute/motionPropertyValues.js.map +1 -0
  60. package/dist/motion/compute/normalize.d.ts +31 -0
  61. package/dist/motion/compute/normalize.js +201 -0
  62. package/dist/motion/compute/normalize.js.map +1 -0
  63. package/dist/motion/compute/validate.d.ts +22 -0
  64. package/dist/motion/compute/validate.js +103 -0
  65. package/dist/motion/compute/validate.js.map +1 -0
  66. package/dist/motion/index.d.ts +8 -0
  67. package/dist/motion/index.js +6 -0
  68. package/dist/motion/index.js.map +1 -0
  69. package/dist/motion/native/serializeMotionTimeline.d.ts +12 -0
  70. package/dist/motion/native/serializeMotionTimeline.js +21 -0
  71. package/dist/motion/native/serializeMotionTimeline.js.map +1 -0
  72. package/dist/physicalMetrics-W5uZ5xKb.d.ts +48 -0
  73. package/dist/physicalMetrics.d.ts +1 -0
  74. package/dist/physicalMetrics.js +58 -0
  75. package/dist/physicalMetrics.js.map +1 -0
  76. package/dist/platform-adapter/CommandResultUtils.d.ts +12 -0
  77. package/dist/platform-adapter/CommandResultUtils.js +21 -0
  78. package/dist/platform-adapter/CommandResultUtils.js.map +1 -0
  79. package/dist/platform-adapter/createPlatformSync.d.ts +16 -0
  80. package/dist/platform-adapter/createPlatformSync.js +30 -0
  81. package/dist/platform-adapter/createPlatformSync.js.map +1 -0
  82. package/dist/platform-adapter/index.d.ts +12 -0
  83. package/dist/platform-adapter/index.js +10 -0
  84. package/dist/platform-adapter/index.js.map +1 -0
  85. package/dist/platform-adapter/interface.d.ts +7 -0
  86. package/dist/platform-adapter/interface.js +1 -0
  87. package/dist/platform-adapter/interface.js.map +1 -0
  88. package/dist/platform-adapter/pico-os/PicoOSPlatform.d.ts +25 -0
  89. package/dist/platform-adapter/pico-os/PicoOSPlatform.js +168 -0
  90. package/dist/platform-adapter/pico-os/PicoOSPlatform.js.map +1 -0
  91. package/dist/platform-adapter/puppeteer/PuppeteerPlatform.d.ts +66 -0
  92. package/dist/platform-adapter/puppeteer/PuppeteerPlatform.js +372 -0
  93. package/dist/platform-adapter/puppeteer/PuppeteerPlatform.js.map +1 -0
  94. package/dist/platform-adapter/spatialRequestMetadata.d.ts +6 -0
  95. package/dist/platform-adapter/spatialRequestMetadata.js +39 -0
  96. package/dist/platform-adapter/spatialRequestMetadata.js.map +1 -0
  97. package/dist/platform-adapter/spatialSceneQuery.d.ts +12 -0
  98. package/dist/platform-adapter/spatialSceneQuery.js +12 -0
  99. package/dist/platform-adapter/spatialSceneQuery.js.map +1 -0
  100. package/dist/platform-adapter/vision-os/VisionOSPlatform.d.ts +19 -0
  101. package/dist/platform-adapter/vision-os/VisionOSPlatform.js +77 -0
  102. package/dist/platform-adapter/vision-os/VisionOSPlatform.js.map +1 -0
  103. package/dist/platform-runtime.d.ts +12 -0
  104. package/dist/platform-runtime.js +14 -0
  105. package/dist/platform-runtime.js.map +1 -0
  106. package/dist/reality/Attachment.d.ts +19 -0
  107. package/dist/reality/Attachment.js +39 -0
  108. package/dist/reality/Attachment.js.map +1 -0
  109. package/dist/reality/component/ModelComponent.d.ts +14 -0
  110. package/dist/reality/component/ModelComponent.js +11 -0
  111. package/dist/reality/component/ModelComponent.js.map +1 -0
  112. package/dist/reality/component/SpatialComponent.d.ts +8 -0
  113. package/dist/reality/component/SpatialComponent.js +19 -0
  114. package/dist/reality/component/SpatialComponent.js.map +1 -0
  115. package/dist/reality/component/index.d.ts +8 -0
  116. package/dist/reality/component/index.js +3 -0
  117. package/dist/reality/component/index.js.map +1 -0
  118. package/dist/reality/entity/SpatialEntity.d.ts +7 -0
  119. package/dist/reality/entity/SpatialEntity.js +291 -0
  120. package/dist/reality/entity/SpatialEntity.js.map +1 -0
  121. package/dist/reality/entity/SpatialModelEntity.d.ts +17 -0
  122. package/dist/reality/entity/SpatialModelEntity.js +17 -0
  123. package/dist/reality/entity/SpatialModelEntity.js.map +1 -0
  124. package/dist/reality/entity/index.d.ts +8 -0
  125. package/dist/reality/entity/index.js +3 -0
  126. package/dist/reality/entity/index.js.map +1 -0
  127. package/dist/reality/geometry/SpatialBoxGeometry.d.ts +16 -0
  128. package/dist/reality/geometry/SpatialBoxGeometry.js +13 -0
  129. package/dist/reality/geometry/SpatialBoxGeometry.js.map +1 -0
  130. package/dist/reality/geometry/SpatialConeGeometry.d.ts +16 -0
  131. package/dist/reality/geometry/SpatialConeGeometry.js +13 -0
  132. package/dist/reality/geometry/SpatialConeGeometry.js.map +1 -0
  133. package/dist/reality/geometry/SpatialCylinderGeometry.d.ts +16 -0
  134. package/dist/reality/geometry/SpatialCylinderGeometry.js +13 -0
  135. package/dist/reality/geometry/SpatialCylinderGeometry.js.map +1 -0
  136. package/dist/reality/geometry/SpatialGeometry.d.ts +7 -0
  137. package/dist/reality/geometry/SpatialGeometry.js +13 -0
  138. package/dist/reality/geometry/SpatialGeometry.js.map +1 -0
  139. package/dist/reality/geometry/SpatialPlaneGeometry.d.ts +16 -0
  140. package/dist/reality/geometry/SpatialPlaneGeometry.js +13 -0
  141. package/dist/reality/geometry/SpatialPlaneGeometry.js.map +1 -0
  142. package/dist/reality/geometry/SpatialSphereGeometry.d.ts +16 -0
  143. package/dist/reality/geometry/SpatialSphereGeometry.js +13 -0
  144. package/dist/reality/geometry/SpatialSphereGeometry.js.map +1 -0
  145. package/dist/reality/geometry/index.d.ts +12 -0
  146. package/dist/reality/geometry/index.js +7 -0
  147. package/dist/reality/geometry/index.js.map +1 -0
  148. package/dist/reality/index.d.ts +18 -0
  149. package/dist/reality/index.js +7 -0
  150. package/dist/reality/index.js.map +1 -0
  151. package/dist/reality/material/SpatialMaterial.d.ts +7 -0
  152. package/dist/reality/material/SpatialMaterial.js +13 -0
  153. package/dist/reality/material/SpatialMaterial.js.map +1 -0
  154. package/dist/reality/material/SpatialUnlitMaterial.d.ts +16 -0
  155. package/dist/reality/material/SpatialUnlitMaterial.js +16 -0
  156. package/dist/reality/material/SpatialUnlitMaterial.js.map +1 -0
  157. package/dist/reality/material/index.d.ts +8 -0
  158. package/dist/reality/material/index.js +3 -0
  159. package/dist/reality/material/index.js.map +1 -0
  160. package/dist/reality/realityCreator.d.ts +22 -0
  161. package/dist/reality/realityCreator.js +89 -0
  162. package/dist/reality/realityCreator.js.map +1 -0
  163. package/dist/reality/resource/SpatialModelAsset.d.ts +15 -0
  164. package/dist/reality/resource/SpatialModelAsset.js +12 -0
  165. package/dist/reality/resource/SpatialModelAsset.js.map +1 -0
  166. package/dist/reality/resource/SpatialTextureResource.d.ts +16 -0
  167. package/dist/reality/resource/SpatialTextureResource.js +16 -0
  168. package/dist/reality/resource/SpatialTextureResource.js.map +1 -0
  169. package/dist/reality/resource/index.d.ts +9 -0
  170. package/dist/reality/resource/index.js +3 -0
  171. package/dist/reality/resource/index.js.map +1 -0
  172. package/dist/runtime/WebSpatialRuntimeError.d.ts +10 -0
  173. package/dist/runtime/WebSpatialRuntimeError.js +14 -0
  174. package/dist/runtime/WebSpatialRuntimeError.js.map +1 -0
  175. package/dist/runtime/capability-data.d.ts +12 -0
  176. package/dist/runtime/capability-data.js +134 -0
  177. package/dist/runtime/capability-data.js.map +1 -0
  178. package/dist/runtime/index.d.ts +8 -0
  179. package/dist/runtime/index.js +27 -0
  180. package/dist/runtime/index.js.map +1 -0
  181. package/dist/runtime/jsbAdapterPlatform.d.ts +9 -0
  182. package/dist/runtime/jsbAdapterPlatform.js +38 -0
  183. package/dist/runtime/jsbAdapterPlatform.js.map +1 -0
  184. package/dist/runtime/keys.d.ts +34 -0
  185. package/dist/runtime/keys.js +122 -0
  186. package/dist/runtime/keys.js.map +1 -0
  187. package/dist/runtime/semver.d.ts +8 -0
  188. package/dist/runtime/semver.js +32 -0
  189. package/dist/runtime/semver.js.map +1 -0
  190. package/dist/runtime/supports.d.ts +22 -0
  191. package/dist/runtime/supports.js +78 -0
  192. package/dist/runtime/supports.js.map +1 -0
  193. package/dist/runtime/types.d.ts +12 -0
  194. package/dist/runtime/types.js +1 -0
  195. package/dist/runtime/types.js.map +1 -0
  196. package/dist/runtime/userAgent.d.ts +20 -0
  197. package/dist/runtime/userAgent.js +41 -0
  198. package/dist/runtime/userAgent.js.map +1 -0
  199. package/dist/scene-polyfill.d.ts +18 -0
  200. package/dist/scene-polyfill.js +480 -0
  201. package/dist/scene-polyfill.js.map +1 -0
  202. package/dist/spatial-host.d.ts +13 -0
  203. package/dist/spatial-host.js +18 -0
  204. package/dist/spatial-host.js.map +1 -0
  205. package/dist/spatial-window-polyfill.d.ts +3 -0
  206. package/dist/spatial-window-polyfill.js +155 -0
  207. package/dist/spatial-window-polyfill.js.map +1 -0
  208. package/dist/spatializedElementMotion-_0XWPQCE.d.ts +1009 -0
  209. package/dist/types/animation.d.ts +7 -0
  210. package/dist/types/animation.js +1 -0
  211. package/dist/types/animation.js.map +1 -0
  212. package/dist/types/global.d.ts +38 -0
  213. package/dist/types/global.js +1 -0
  214. package/dist/types/global.js.map +1 -0
  215. package/dist/types/internal.d.ts +7 -0
  216. package/dist/types/internal.js +12 -0
  217. package/dist/types/internal.js.map +1 -0
  218. package/dist/types/motion/index.d.ts +7 -0
  219. package/dist/types/motion/index.js +3 -0
  220. package/dist/types/motion/index.js.map +1 -0
  221. package/dist/types/motion/spatializedElementMotion.d.ts +7 -0
  222. package/dist/types/motion/spatializedElementMotion.js +1 -0
  223. package/dist/types/motion/spatializedElementMotion.js.map +1 -0
  224. package/dist/types/motion/spatializedMotion.d.ts +7 -0
  225. package/dist/types/motion/spatializedMotion.js +16 -0
  226. package/dist/types/motion/spatializedMotion.js.map +1 -0
  227. package/dist/types/motion/spatializedPlayback.d.ts +11 -0
  228. package/dist/types/motion/spatializedPlayback.js +1 -0
  229. package/dist/types/motion/spatializedPlayback.js.map +1 -0
  230. package/dist/types/motion/spatializedVisual.d.ts +35 -0
  231. package/dist/types/motion/spatializedVisual.js +1 -0
  232. package/dist/types/motion/spatializedVisual.js.map +1 -0
  233. package/dist/types/types.d.ts +7 -0
  234. package/dist/types/types.js +117 -0
  235. package/dist/types/types.js.map +1 -0
  236. package/dist/utils.d.ts +44 -0
  237. package/dist/utils.js +86 -0
  238. package/dist/utils.js.map +1 -0
  239. package/package.json +20 -4
  240. package/src/JSBCommand.ts +132 -5
  241. package/src/SpatialObject.ts +10 -0
  242. package/src/Spatialized2DElement.ts +5 -0
  243. package/src/SpatializedDynamic3DElement.ts +5 -0
  244. package/src/SpatializedElement.ts +29 -0
  245. package/src/SpatializedStatic3DElement.ts +42 -3
  246. package/src/WebMsgCommand.ts +40 -0
  247. package/src/coverage-boost.test.ts +239 -216
  248. package/src/index.ts +25 -11
  249. package/src/install-polyfills.ts +38 -0
  250. package/src/jsbcommand.coverage.test.ts +23 -0
  251. package/src/motion/AnimationObject.test.ts +421 -0
  252. package/src/motion/AnimationObject.ts +208 -0
  253. package/src/motion/compute/index.ts +10 -0
  254. package/src/motion/compute/motionPropertyValues.test.ts +55 -0
  255. package/src/motion/compute/motionPropertyValues.ts +70 -0
  256. package/src/motion/compute/normalize.test.ts +99 -0
  257. package/src/motion/compute/normalize.ts +289 -0
  258. package/src/motion/compute/validate.test.ts +229 -0
  259. package/src/motion/compute/validate.ts +156 -0
  260. package/src/motion/index.ts +2 -0
  261. package/src/motion/native/serializeMotionTimeline.test.ts +61 -0
  262. package/src/motion/native/serializeMotionTimeline.ts +27 -0
  263. package/src/platform-adapter/createPlatformSync.ts +5 -3
  264. package/src/platform-adapter/pico-os/PicoOSPlatform.ts +76 -11
  265. package/src/platform-adapter/spatialRequestMetadata.test.ts +175 -0
  266. package/src/platform-adapter/spatialRequestMetadata.ts +48 -0
  267. package/src/platform-adapter/vision-os/VisionOSPlatform.ts +6 -1
  268. package/src/reality/entity/SpatialEntity.ts +127 -0
  269. package/src/runtime/capability-data.ts +104 -4
  270. package/src/runtime/index.ts +0 -11
  271. package/src/runtime/keys.ts +12 -1
  272. package/src/runtime/supports.test.ts +143 -4
  273. package/src/runtime/supports.ts +3 -1
  274. package/src/runtime/useAnimation.capability.test.ts +275 -0
  275. package/src/scene-polyfill.manifest.test.ts +306 -5
  276. package/src/scene-polyfill.request-metadata.test.ts +39 -0
  277. package/src/scene-polyfill.test.ts +33 -94
  278. package/src/scene-polyfill.ts +117 -87
  279. package/src/spatial-window-polyfill.ts +18 -2
  280. package/src/transform-roundtrip.test.ts +90 -0
  281. package/src/types/animation.ts +224 -0
  282. package/src/types/global.ts +1 -8
  283. package/src/types/motion/index.ts +10 -0
  284. package/src/types/motion/spatializedElementMotion.ts +49 -0
  285. package/src/types/motion/spatializedMotion.ts +147 -0
  286. package/src/types/motion/spatializedPlayback.ts +17 -0
  287. package/src/types/motion/spatializedVisual.ts +24 -0
  288. package/src/types/types.ts +3 -0
  289. package/src/utils.ts +54 -0
  290. package/tsup.config.ts +61 -36
  291. package/vitest.config.ts +5 -1
  292. package/dist/iife/index.d.ts +0 -1251
  293. package/dist/iife/index.global.js +0 -75
  294. package/dist/iife/index.global.js.map +0 -1
  295. package/src/platform-adapter/ssr/SSRPlatform.ts +0 -52
  296. /package/src/{ssr-polyfill.ts → isSSREnv.ts} +0 -0
@@ -1,17 +1,35 @@
1
- import { describe, it, expect, vi } from 'vitest'
1
+ import { afterEach, describe, expect, it, vi } from 'vitest'
2
+
3
+ const jsbMocks = vi.hoisted(() => ({
4
+ createSpatialSceneCommand: vi.fn().mockImplementation(() => ({
5
+ executeSync: vi.fn().mockReturnValue({
6
+ data: { id: 'scene-1', windowProxy: {} },
7
+ }),
8
+ })),
9
+ focusSceneExecute: vi.fn().mockResolvedValue(undefined),
10
+ }))
2
11
 
3
- vi.mock('./spatial-host', () => ({
12
+ const spatialHostMocks = vi.hoisted(() => ({
4
13
  openSpatialSceneSync: vi.fn().mockReturnValue({
5
14
  success: true,
6
15
  data: { id: 'scene-1', windowProxy: {} },
7
16
  }),
8
17
  }))
9
18
 
19
+ const originalWindowOpen = window.open
20
+
21
+ vi.mock('./spatial-host', () => ({
22
+ openSpatialSceneSync: spatialHostMocks.openSpatialSceneSync,
23
+ }))
24
+
10
25
  vi.mock('./JSBCommand', () => {
11
26
  return {
12
- FocusScene: vi.fn().mockImplementation(() => ({
13
- execute: vi.fn().mockResolvedValue(undefined),
14
- })),
27
+ createSpatialSceneCommand: jsbMocks.createSpatialSceneCommand,
28
+ FocusScene: vi.fn().mockImplementation(function () {
29
+ return {
30
+ execute: jsbMocks.focusSceneExecute,
31
+ }
32
+ }),
15
33
  }
16
34
  })
17
35
 
@@ -31,6 +49,16 @@ async function waitTick() {
31
49
  await new Promise(r => setTimeout(r, 0))
32
50
  }
33
51
 
52
+ afterEach(() => {
53
+ window.open = originalWindowOpen
54
+ jsbMocks.createSpatialSceneCommand.mockClear()
55
+ jsbMocks.focusSceneExecute.mockClear()
56
+ spatialHostMocks.openSpatialSceneSync.mockClear()
57
+ document
58
+ .querySelectorAll('link[rel="manifest"]')
59
+ .forEach(node => node.parentElement?.removeChild(node))
60
+ })
61
+
34
62
  describe('setupManifest applies overrides to xr_window_defaults / xr_volume_defaults', () => {
35
63
  it('applies window overrides without affecting volume defaults', async () => {
36
64
  vi.resetModules()
@@ -111,6 +139,279 @@ describe('setupManifest applies overrides to xr_window_defaults / xr_volume_defa
111
139
  cleanup()
112
140
  })
113
141
 
142
+ it('prefers snake_case over camelCase within a layer and still applies overrides by priority', async () => {
143
+ vi.resetModules()
144
+ const cleanup = addDataManifest({
145
+ xr_spatial_scene: {
146
+ defaultSize: { width: '111px', height: '111px' },
147
+ default_size: { width: '222px', height: '333px' },
148
+ overrides: {
149
+ window_scene: {
150
+ defaultSize: { width: '444px' },
151
+ default_size: { width: '555px' },
152
+ },
153
+ },
154
+ },
155
+ })
156
+ const { hijackWindowOpen, initScene } = await import('./scene-polyfill')
157
+ hijackWindowOpen(window)
158
+ await waitTick()
159
+
160
+ let winDefaults: any
161
+ initScene(
162
+ 'w',
163
+ pre => {
164
+ winDefaults = pre
165
+ return pre
166
+ },
167
+ { type: 'window' },
168
+ )
169
+
170
+ let volDefaults: any
171
+ initScene(
172
+ 'v',
173
+ pre => {
174
+ volDefaults = pre
175
+ return pre
176
+ },
177
+ { type: 'volume' },
178
+ )
179
+
180
+ expect(winDefaults).toEqual(
181
+ expect.objectContaining({
182
+ defaultSize: { width: '555px', height: '333px' },
183
+ }),
184
+ )
185
+
186
+ expect(volDefaults).toEqual(
187
+ expect.objectContaining({
188
+ defaultSize: { width: '222px', height: '333px' },
189
+ }),
190
+ )
191
+
192
+ cleanup()
193
+ })
194
+
195
+ it('resolves same-layer aliases recursively so winners own their layer values', async () => {
196
+ vi.resetModules()
197
+ const cleanup = addDataManifest({
198
+ xr_spatial_scene: {
199
+ defaultSize: { width: '111px', height: '111px' },
200
+ default_size: { width: '222px', height: '333px' },
201
+ resizability: {
202
+ minWidth: '100px',
203
+ min_width: '200px',
204
+ maxWidth: '800px',
205
+ },
206
+ },
207
+ })
208
+ const { hijackWindowOpen, initScene } = await import('./scene-polyfill')
209
+ hijackWindowOpen(window)
210
+ await waitTick()
211
+
212
+ let defaults: any
213
+ initScene(
214
+ 'recursive-layer',
215
+ pre => {
216
+ defaults = pre
217
+ return pre
218
+ },
219
+ { type: 'window' },
220
+ )
221
+
222
+ expect(defaults).toEqual(
223
+ expect.objectContaining({
224
+ defaultSize: { width: '222px', height: '333px' },
225
+ resizability: {
226
+ minWidth: '200px',
227
+ maxWidth: '800px',
228
+ },
229
+ }),
230
+ )
231
+
232
+ cleanup()
233
+ })
234
+
235
+ it('supports overrides windowScene/volumeScene and snake_case resizability keys', async () => {
236
+ vi.resetModules()
237
+ const cleanup = addDataManifest({
238
+ xr_spatial_scene: {
239
+ resizability: {
240
+ min_width: '300px',
241
+ min_height: '400px',
242
+ max_width: '1200px',
243
+ max_height: '1300px',
244
+ },
245
+ worldScaling: 'automatic',
246
+ overrides: {
247
+ windowScene: {
248
+ world_scaling: 'dynamic',
249
+ },
250
+ volumeScene: {
251
+ baseplate_visibility: 'hidden',
252
+ },
253
+ },
254
+ },
255
+ })
256
+ const { hijackWindowOpen, initScene } = await import('./scene-polyfill')
257
+ hijackWindowOpen(window)
258
+ await waitTick()
259
+
260
+ let winDefaults: any
261
+ initScene(
262
+ 'w',
263
+ pre => {
264
+ winDefaults = pre
265
+ return pre
266
+ },
267
+ { type: 'window' },
268
+ )
269
+
270
+ let volDefaults: any
271
+ initScene(
272
+ 'v',
273
+ pre => {
274
+ volDefaults = pre
275
+ return pre
276
+ },
277
+ { type: 'volume' },
278
+ )
279
+
280
+ expect(winDefaults).toEqual(
281
+ expect.objectContaining({
282
+ resizability: {
283
+ minWidth: '300px',
284
+ minHeight: '400px',
285
+ maxWidth: '1200px',
286
+ maxHeight: '1300px',
287
+ },
288
+ worldScaling: 'dynamic',
289
+ }),
290
+ )
291
+
292
+ expect(volDefaults).toEqual(
293
+ expect.objectContaining({
294
+ resizability: {
295
+ minWidth: '300px',
296
+ minHeight: '400px',
297
+ maxWidth: '1200px',
298
+ maxHeight: '1300px',
299
+ },
300
+ baseplateVisibility: 'hidden',
301
+ }),
302
+ )
303
+
304
+ cleanup()
305
+ })
306
+
307
+ it('normalizes top-level world_alignment and baseplate_visibility aliases', async () => {
308
+ vi.resetModules()
309
+ const cleanup = addDataManifest({
310
+ xr_spatial_scene: {
311
+ world_alignment: 'gravityAligned',
312
+ baseplate_visibility: 'hidden',
313
+ },
314
+ })
315
+ const { hijackWindowOpen, initScene } = await import('./scene-polyfill')
316
+ hijackWindowOpen(window)
317
+ await waitTick()
318
+
319
+ let winDefaults: any
320
+ initScene(
321
+ 'w-alias',
322
+ pre => {
323
+ winDefaults = pre
324
+ return pre
325
+ },
326
+ { type: 'window' },
327
+ )
328
+
329
+ let volDefaults: any
330
+ initScene(
331
+ 'v-alias',
332
+ pre => {
333
+ volDefaults = pre
334
+ return pre
335
+ },
336
+ { type: 'volume' },
337
+ )
338
+
339
+ expect(winDefaults).toEqual(
340
+ expect.objectContaining({
341
+ worldAlignment: 'gravityAligned',
342
+ baseplateVisibility: 'hidden',
343
+ }),
344
+ )
345
+ expect(volDefaults).toEqual(
346
+ expect.objectContaining({
347
+ worldAlignment: 'gravityAligned',
348
+ baseplateVisibility: 'hidden',
349
+ }),
350
+ )
351
+
352
+ cleanup()
353
+ })
354
+
355
+ it('does not normalize initScene callback return value when chaining', async () => {
356
+ vi.resetModules()
357
+ const cleanup = addDataManifest({
358
+ xr_spatial_scene: {
359
+ default_size: { width: '222px', height: '333px' },
360
+ },
361
+ })
362
+ const { hijackWindowOpen, initScene } = await import('./scene-polyfill')
363
+ hijackWindowOpen(window)
364
+ await waitTick()
365
+
366
+ const firstReturn: any = { default_size: { width: '777px' } }
367
+ const cb1 = vi.fn().mockReturnValue(firstReturn)
368
+ initScene('chain', cb1, { type: 'window' })
369
+
370
+ const cb2 = vi.fn().mockReturnValue({})
371
+ initScene('chain', cb2, { type: 'window' })
372
+
373
+ expect(cb2).toHaveBeenCalledWith(firstReturn)
374
+
375
+ cleanup()
376
+ })
377
+
378
+ it('uses manifest aliases when window.open creates a named scene without initScene', async () => {
379
+ vi.resetModules()
380
+ const cleanup = addDataManifest({
381
+ xr_spatial_scene: {
382
+ default_size: { width: '300px', height: '400px' },
383
+ world_alignment: 'gravityAligned',
384
+ overrides: {
385
+ windowScene: {
386
+ default_size: { width: '500px' },
387
+ resizability: { min_width: '320px' },
388
+ baseplate_visibility: 'visible',
389
+ },
390
+ },
391
+ },
392
+ })
393
+ const { hijackWindowOpen } = await import('./scene-polyfill')
394
+ hijackWindowOpen(window)
395
+ await waitTick()
396
+
397
+ window.open('https://example.com/scene', 'manifest-alias-window')
398
+
399
+ expect(spatialHostMocks.openSpatialSceneSync).toHaveBeenCalledWith(
400
+ 'https://example.com/scene',
401
+ expect.objectContaining({
402
+ type: 'window',
403
+ defaultSize: { width: 500, height: 400 },
404
+ resizability: { minWidth: 320 },
405
+ worldAlignment: 'gravityAligned',
406
+ baseplateVisibility: 'visible',
407
+ }),
408
+ 'manifest-alias-window',
409
+ undefined,
410
+ )
411
+
412
+ cleanup()
413
+ })
414
+
114
415
  it('applies volume overrides without affecting window defaults', async () => {
115
416
  vi.resetModules()
116
417
  const cleanup = addDataManifest({
@@ -0,0 +1,39 @@
1
+ import { afterEach, describe, expect, it, vi } from 'vitest'
2
+
3
+ describe('scene polyfill request metadata forwarding', () => {
4
+ afterEach(() => {
5
+ vi.restoreAllMocks()
6
+ vi.resetModules()
7
+ delete (window as any).webSpatial
8
+ delete (window as any).__webspatialShell__
9
+ })
10
+
11
+ it.each(['createSpatialized2DElement', 'createAttachment'])(
12
+ 'forwards rid and wsepoch for %s without introducing extra request fields',
13
+ async command => {
14
+ ;(window as any).webSpatial = {
15
+ genToken: vi.fn(() => 'token-123'),
16
+ }
17
+ const originalOpen = vi.fn(() => null)
18
+ vi.spyOn(window, 'open').mockImplementation(originalOpen)
19
+
20
+ const { hijackWindowOpen } = await import('./scene-polyfill')
21
+ hijackWindowOpen(window)
22
+
23
+ window.open(`webspatial://${command}?rid=req_1&wsepoch=9`, '_blank')
24
+
25
+ expect(originalOpen).toHaveBeenCalled()
26
+ const redirectedUrl = (originalOpen.mock.calls as unknown[][])[0]?.[0]
27
+ expect(typeof redirectedUrl).toBe('string')
28
+ const redirected = new URL(String(redirectedUrl))
29
+ if (redirected.protocol === 'webspatial:') {
30
+ expect(redirected.host).toBe(command)
31
+ } else {
32
+ expect(redirected.searchParams.get('command')).toBe(command)
33
+ }
34
+ expect(redirected.searchParams.get('rid')).toBe('req_1')
35
+ expect(redirected.searchParams.get('wsepoch')).toBe('9')
36
+ expect(redirected.searchParams.get('wsrid')).toBeNull()
37
+ },
38
+ )
39
+ })
@@ -265,93 +265,51 @@ describe('test formatSceneConfig in volume', () => {
265
265
 
266
266
  vi.mock('./JSBCommand', () => {
267
267
  return {
268
- GetSpatialSceneState: vi.fn().mockImplementation(() => ({
269
- execute: vi.fn().mockResolvedValue({ data: { name: 'pending' } }),
270
- })),
271
- UpdateSceneConfig: vi.fn().mockImplementation(() => ({
272
- execute: vi.fn().mockResolvedValue(undefined),
273
- })),
274
- UpdateSpatialSceneProperties: vi.fn().mockImplementation(() => ({
275
- execute: vi.fn().mockResolvedValue(undefined),
276
- })),
277
- AddSpatializedElementToSpatialScene: vi.fn().mockImplementation(() => ({
278
- execute: vi.fn().mockResolvedValue(undefined),
279
- })),
268
+ GetSpatialSceneState: vi.fn().mockImplementation(function () {
269
+ return {
270
+ execute: vi.fn().mockResolvedValue({ data: { name: 'pending' } }),
271
+ }
272
+ }),
273
+ UpdateSceneConfig: vi.fn().mockImplementation(function () {
274
+ return {
275
+ execute: vi.fn().mockResolvedValue(undefined),
276
+ }
277
+ }),
278
+ UpdateSpatialSceneProperties: vi.fn().mockImplementation(function () {
279
+ return {
280
+ execute: vi.fn().mockResolvedValue(undefined),
281
+ }
282
+ }),
283
+ AddSpatializedElementToSpatialScene: vi
284
+ .fn()
285
+ .mockImplementation(function () {
286
+ return {
287
+ execute: vi.fn().mockResolvedValue(undefined),
288
+ }
289
+ }),
280
290
  }
281
291
  })
282
292
 
283
- describe('injectScenePolyfill should call xrCurrentSceneDefaults and update scene config', () => {
293
+ describe('removed scene window globals', () => {
284
294
  beforeEach(() => {
285
295
  ;(window as any).opener = {}
286
296
  })
287
297
 
288
- it('with no type', async () => {
289
- vi.useFakeTimers()
290
-
291
- const mockFn = vi
292
- .fn()
293
- .mockResolvedValue({ defaultSize: { width: 800, height: 600 } })
294
- window.xrCurrentSceneDefaults = mockFn
295
-
296
- injectSceneHook()
297
-
298
- document.dispatchEvent(new Event('DOMContentLoaded'))
299
-
300
- await vi.runAllTimersAsync()
301
-
302
- expect(mockFn).toHaveBeenCalledWith(
303
- expect.objectContaining({ defaultSize: { width: 1280, height: 720 } }),
304
- )
305
-
306
- // verify UpdateSceneConfig.execute
307
- const { UpdateSceneConfig } = await import('./JSBCommand')
308
- expect(UpdateSceneConfig).toHaveBeenCalledWith({
309
- type: 'window',
310
- defaultSize: { width: 800, height: 600 },
311
- })
298
+ it('does not type removed window scene globals', () => {
299
+ // @ts-expect-error removed undocumented scene global
300
+ void window.xrCurrentSceneDefaults
301
+ // @ts-expect-error removed undocumented scene global
302
+ void window.xrCurrentSceneType
312
303
  })
313
304
 
314
- it('with window type', async () => {
305
+ it('does not use opened-page globals to override pending scene config', async () => {
315
306
  vi.useFakeTimers()
316
307
 
317
308
  const mockFn = vi
318
309
  .fn()
319
310
  .mockResolvedValue({ defaultSize: { width: 800, height: 600 } })
320
- window.xrCurrentSceneDefaults = mockFn
321
- window.xrCurrentSceneType = 'window'
322
-
323
- injectSceneHook()
324
-
325
- document.dispatchEvent(new Event('DOMContentLoaded'))
326
-
327
- await vi.runAllTimersAsync()
328
-
329
- expect(mockFn).toHaveBeenCalledWith(
330
- expect.objectContaining({ defaultSize: { width: 1280, height: 720 } }),
331
- )
332
-
333
- // verify UpdateSceneConfig.execute
334
- const { UpdateSceneConfig } = await import('./JSBCommand')
335
- expect(UpdateSceneConfig).toHaveBeenCalledWith({
336
- type: 'window',
337
- defaultSize: { width: 800, height: 600 },
338
- })
339
- })
340
-
341
- it('with volume type', async () => {
342
- vi.useFakeTimers()
343
-
344
- const mockFn = vi.fn().mockResolvedValue({
345
- defaultSize: { width: 1, height: 1, depth: 1 },
346
- resizability: {
347
- minWidth: 0.5,
348
- minHeight: 1,
349
- maxWidth: 0.5,
350
- maxHeight: 1,
351
- },
352
- })
353
- window.xrCurrentSceneDefaults = mockFn
354
- window.xrCurrentSceneType = 'volume'
311
+ ;(window as any).xrCurrentSceneDefaults = mockFn
312
+ ;(window as any).xrCurrentSceneType = 'volume'
355
313
 
356
314
  injectSceneHook()
357
315
 
@@ -359,28 +317,9 @@ describe('injectScenePolyfill should call xrCurrentSceneDefaults and update scen
359
317
 
360
318
  await vi.runAllTimersAsync()
361
319
 
362
- expect(mockFn).toHaveBeenCalledWith(
363
- expect.objectContaining({
364
- defaultSize: { width: '0.94m', height: '0.94m', depth: '0.94m' },
365
- }),
366
- )
367
-
368
- // verify UpdateSceneConfig.execute
369
320
  const { UpdateSceneConfig } = await import('./JSBCommand')
370
- expect(UpdateSceneConfig).toHaveBeenCalledWith({
371
- type: 'volume',
372
- defaultSize: {
373
- width: pointToPhysical(1),
374
- height: pointToPhysical(1),
375
- depth: pointToPhysical(1),
376
- },
377
- resizability: {
378
- minWidth: 0.5,
379
- minHeight: 1,
380
- maxWidth: 0.5,
381
- maxHeight: 1,
382
- },
383
- })
321
+ expect(mockFn).not.toHaveBeenCalled()
322
+ expect(UpdateSceneConfig).not.toHaveBeenCalled()
384
323
  })
385
324
  })
386
325