@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,4 +1,4 @@
1
- import { describe, expect, test, vi, beforeEach } from 'vitest'
1
+ import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'
2
2
 
3
3
  describe('getRuntime / supports', () => {
4
4
  beforeEach(() => {
@@ -81,7 +81,7 @@ describe('getRuntime / supports', () => {
81
81
  expect(supports('xrOuterDepth')).toBe(false)
82
82
  })
83
83
 
84
- test('pico UA PicoWebApp/0.1.2: matrix playback row (alpha2.0)', async () => {
84
+ test('pico UA PicoWebApp/0.1.2: matrix playback row (beta2.0)', async () => {
85
85
  vi.stubGlobal('navigator', {
86
86
  userAgent:
87
87
  'Mozilla/5.0 (X11; Linux x86_64; unknown OS0.11.0 like Quest) AppleWebKit/537.36 PicoWebApp/0.1.2 (like PicoBrowser) Chrome/138.0 WebSpatial/1.5.0',
@@ -89,12 +89,40 @@ describe('getRuntime / supports', () => {
89
89
  const { supports, resetRuntimeCacheForTests } = await import('./supports')
90
90
  resetRuntimeCacheForTests()
91
91
  expect(supports('Model', ['autoplay', 'loop', 'source'])).toBe(true)
92
- expect(supports('Model', ['currentTime'])).toBe(false)
93
- expect(supports('Model', ['poster'])).toBe(false)
92
+ expect(supports('Model', ['currentTime'])).toBe(true)
93
+ expect(supports('Model', ['poster'])).toBe(true)
94
+ expect(supports('Model', ['loading'])).toBe(false)
95
+ expect(supports('xrInnerDepth')).toBe(false)
96
+ expect(supports('xrOuterDepth')).toBe(false)
97
+ })
98
+
99
+ test('pico UA PicoWebApp/0.3.1: beta2.1 enables Model loading', async () => {
100
+ vi.stubGlobal('navigator', {
101
+ userAgent:
102
+ 'Mozilla/5.0 (X11; Linux x86_64; unknown OS0.11.0 like Quest) AppleWebKit/537.36 PicoWebApp/0.3.1 (like PicoBrowser) Chrome/138.0 WebSpatial/1.5.0',
103
+ } as Navigator)
104
+ const { supports, resetRuntimeCacheForTests } = await import('./supports')
105
+ resetRuntimeCacheForTests()
106
+ expect(supports('Model', ['currentTime', 'poster', 'loading'])).toBe(true)
107
+ expect(supports('Model', ['stagemode'])).toBe(false)
108
+ expect(supports('useAnimation')).toBe(false)
109
+ expect(supports('useAnimation', ['entity'])).toBe(false)
94
110
  expect(supports('xrInnerDepth')).toBe(false)
95
111
  expect(supports('xrOuterDepth')).toBe(false)
96
112
  })
97
113
 
114
+ test('pico UA above PicoWebApp/0.3.1 keeps its capabilities before OTA0', async () => {
115
+ vi.stubGlobal('navigator', {
116
+ userAgent:
117
+ 'Mozilla/5.0 (X11; Linux x86_64; unknown OS0.11.0 like Quest) AppleWebKit/537.36 PicoWebApp/0.3.2 (like PicoBrowser) Chrome/138.0 WebSpatial/1.5.0',
118
+ } as Navigator)
119
+ const { supports, resetRuntimeCacheForTests } = await import('./supports')
120
+ resetRuntimeCacheForTests()
121
+ expect(supports('Model', ['currentTime', 'poster', 'loading'])).toBe(true)
122
+ expect(supports('useAnimation')).toBe(false)
123
+ expect(supports('useAnimation', ['entity'])).toBe(false)
124
+ })
125
+
98
126
  test('alias Box → BoxEntity', async () => {
99
127
  vi.stubGlobal('navigator', {
100
128
  userAgent:
@@ -204,4 +232,115 @@ describe('getRuntime / supports', () => {
204
232
  expect(supports('Model', ['poster'])).toBe(false)
205
233
  expect(supports('Model', ['play', 'pause', 'duration'])).toBe(true)
206
234
  })
235
+
236
+ test('visionOS WSAppShell/1.7.0: Model currentTime, loading, and poster are supported', async () => {
237
+ vi.stubGlobal('navigator', {
238
+ userAgent:
239
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7; wv) AppleWebKit/605.1.15 (KHTML, like Gecko) WSAppShell/1.7.0 WebSpatial/1.5.0 Safari/537.36',
240
+ } as Navigator)
241
+ const { supports, resetRuntimeCacheForTests } = await import('./supports')
242
+ resetRuntimeCacheForTests()
243
+ expect(supports('Model', ['currentTime', 'loading', 'poster'])).toBe(true)
244
+ expect(supports('Model', ['stagemode'])).toBe(false)
245
+ expect(supports('useAnimation')).toBe(false)
246
+ expect(supports('useAnimation', ['entity'])).toBe(false)
247
+ })
248
+
249
+ test('visionOS WSAppShell/1.8.0: useAnimation is true while sub-tokens are false', async () => {
250
+ vi.stubGlobal('navigator', {
251
+ userAgent:
252
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7; wv) AppleWebKit/605.1.15 WSAppShell/1.8.0 WebSpatial/1.5.0 Safari/537.36',
253
+ } as Navigator)
254
+ const { supports, resetRuntimeCacheForTests } = await import('./supports')
255
+ resetRuntimeCacheForTests()
256
+ expect(supports('useAnimation')).toBe(true)
257
+ expect(supports('useAnimation', ['entity'])).toBe(false)
258
+ expect(supports('useAnimation', ['element'])).toBe(false)
259
+ })
260
+
261
+ test('useAnimation rejects all sub-tokens', async () => {
262
+ vi.stubGlobal('navigator', {
263
+ userAgent:
264
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7; wv) AppleWebKit/605.1.15 WSAppShell/1.7.0 WebSpatial/1.5.0 Safari/537.36',
265
+ } as Navigator)
266
+ const { supports, resetRuntimeCacheForTests } = await import('./supports')
267
+ resetRuntimeCacheForTests()
268
+ expect(supports('useAnimation')).toBe(false)
269
+ expect(supports('useAnimation', ['entity'])).toBe(false)
270
+ expect(supports('useAnimation', ['element'])).toBe(false)
271
+ expect(supports('useAnimation', ['static3d'])).toBe(false)
272
+ expect(supports('useAnimation', ['dynamic3d'])).toBe(false)
273
+
274
+ vi.stubGlobal('navigator', {
275
+ userAgent:
276
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 WSAppShell/1.5.0 WebSpatial/1.5.0',
277
+ } as Navigator)
278
+ const mod2 = await import('./supports')
279
+ mod2.resetRuntimeCacheForTests()
280
+ expect(mod2.supports('useAnimation')).toBe(false)
281
+ expect(mod2.supports('useAnimation', ['entity'])).toBe(false)
282
+ expect(mod2.supports('useAnimation', ['element'])).toBe(false)
283
+ })
284
+
285
+ test('useAnimation result is stable across repeated calls', async () => {
286
+ vi.stubGlobal('navigator', {
287
+ userAgent:
288
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7; wv) AppleWebKit/605.1.15 WSAppShell/1.8.0 WebSpatial/1.5.0 Safari/537.36',
289
+ } as Navigator)
290
+ const { supports, resetRuntimeCacheForTests } = await import('./supports')
291
+ resetRuntimeCacheForTests()
292
+ const first = supports('useAnimation')
293
+ const second = supports('useAnimation')
294
+ const third = supports('useAnimation')
295
+ expect(first).toBe(true)
296
+ expect(second).toBe(true)
297
+ expect(third).toBe(true)
298
+ })
299
+ })
300
+
301
+ describe('supports("useAnimation") for motion', () => {
302
+ afterEach(() => {
303
+ vi.unstubAllGlobals()
304
+ })
305
+
306
+ test('visionOS WSAppShell/1.8.0: useAnimation is true while sub-tokens are false', async () => {
307
+ vi.stubGlobal('navigator', {
308
+ userAgent:
309
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7; wv) AppleWebKit/605.1.15 WSAppShell/1.8.0 WebSpatial/1.5.0 Safari/537.36',
310
+ } as Navigator)
311
+ const { supports, resetRuntimeCacheForTests } = await import('./supports')
312
+ resetRuntimeCacheForTests()
313
+ expect(supports('useAnimation')).toBe(true)
314
+ expect(supports('useAnimation', [])).toBe(true)
315
+ expect(supports('useAnimation', ['entity'])).toBe(false)
316
+ expect(supports('useAnimation', ['element'])).toBe(false)
317
+ expect(supports('useAnimation', ['static3d'])).toBe(false)
318
+ expect(supports('useAnimation', ['dynamic3d'])).toBe(false)
319
+ })
320
+
321
+ test('visionOS WSAppShell/1.7.0: useAnimation and sub-tokens are false', async () => {
322
+ vi.stubGlobal('navigator', {
323
+ userAgent:
324
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7; wv) AppleWebKit/605.1.15 WSAppShell/1.7.0 WebSpatial/1.5.0 Safari/537.36',
325
+ } as Navigator)
326
+ const { supports, resetRuntimeCacheForTests } = await import('./supports')
327
+ resetRuntimeCacheForTests()
328
+ expect(supports('useAnimation')).toBe(false)
329
+ expect(supports('useAnimation', [])).toBe(false)
330
+ expect(supports('useAnimation', ['entity'])).toBe(false)
331
+ expect(supports('useAnimation', ['element'])).toBe(false)
332
+ expect(supports('useAnimation', ['static3d'])).toBe(false)
333
+ expect(supports('useAnimation', ['dynamic3d'])).toBe(false)
334
+ })
335
+
336
+ test('visionOS WSAppShell/1.6.0: element token remains false', async () => {
337
+ vi.stubGlobal('navigator', {
338
+ userAgent:
339
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7; wv) AppleWebKit/605.1.15 WSAppShell/1.6.0 WebSpatial/1.5.0 Safari/537.36',
340
+ } as Navigator)
341
+ const { supports, resetRuntimeCacheForTests } = await import('./supports')
342
+ resetRuntimeCacheForTests()
343
+ expect(supports('useAnimation')).toBe(false)
344
+ expect(supports('useAnimation', ['element'])).toBe(false)
345
+ })
207
346
  })
@@ -105,6 +105,8 @@ export function supports(name: string, tokens?: readonly string[]): boolean {
105
105
  if (tokList.length === 0) {
106
106
  return row.flags[canonical] === true
107
107
  }
108
- if (row.flags[canonical] !== true) return false
108
+ if (row.flags[canonical] !== true) {
109
+ return false
110
+ }
109
111
  return tokList.every(t => row.flags[`${canonical}:${t}`] === true)
110
112
  }
@@ -0,0 +1,275 @@
1
+ import { describe, expect, test, vi, beforeEach } from 'vitest'
2
+
3
+ describe('supports("useAnimation")', () => {
4
+ beforeEach(() => {
5
+ vi.resetModules()
6
+ })
7
+
8
+ test('plain browser: supports("useAnimation") is false', async () => {
9
+ vi.stubGlobal('navigator', {
10
+ userAgent:
11
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36',
12
+ } as Navigator)
13
+ const { supports, resetRuntimeCacheForTests } = await import('./supports')
14
+ resetRuntimeCacheForTests()
15
+ expect(supports('useAnimation')).toBe(false)
16
+ })
17
+
18
+ test('visionOS WSAppShell/1.5.0: supports("useAnimation") is false', async () => {
19
+ vi.stubGlobal('navigator', {
20
+ userAgent:
21
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 WSAppShell/1.5.0 WebSpatial/1.5.0',
22
+ } as Navigator)
23
+ const { supports, resetRuntimeCacheForTests } = await import('./supports')
24
+ resetRuntimeCacheForTests()
25
+ expect(supports('useAnimation')).toBe(false)
26
+ })
27
+
28
+ test('visionOS WSAppShell/1.6.0: supports("useAnimation") is false', async () => {
29
+ vi.stubGlobal('navigator', {
30
+ userAgent:
31
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7; wv) AppleWebKit/605.1.15 (KHTML, like Gecko) WSAppShell/1.6.0 WebSpatial/1.5.0 Safari/537.36',
32
+ } as Navigator)
33
+ const { supports, resetRuntimeCacheForTests } = await import('./supports')
34
+ resetRuntimeCacheForTests()
35
+ expect(supports('useAnimation')).toBe(false)
36
+ })
37
+
38
+ test('visionOS WSAppShell/1.7.0: supports("useAnimation") is false', async () => {
39
+ vi.stubGlobal('navigator', {
40
+ userAgent:
41
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7; wv) AppleWebKit/605.1.15 (KHTML, like Gecko) WSAppShell/1.7.0 WebSpatial/1.5.0 Safari/537.36',
42
+ } as Navigator)
43
+ const { supports, resetRuntimeCacheForTests } = await import('./supports')
44
+ resetRuntimeCacheForTests()
45
+ expect(supports('useAnimation')).toBe(false)
46
+ })
47
+
48
+ test('visionOS WSAppShell/1.8.0: supports("useAnimation") is true', async () => {
49
+ vi.stubGlobal('navigator', {
50
+ userAgent:
51
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7; wv) AppleWebKit/605.1.15 (KHTML, like Gecko) WSAppShell/1.8.0 WebSpatial/1.5.0 Safari/537.36',
52
+ } as Navigator)
53
+ const { supports, resetRuntimeCacheForTests } = await import('./supports')
54
+ resetRuntimeCacheForTests()
55
+ expect(supports('useAnimation')).toBe(true)
56
+ })
57
+
58
+ test('Puppeteer UA: supports("useAnimation") is true (debug mode enables all)', async () => {
59
+ vi.stubGlobal('navigator', {
60
+ userAgent:
61
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 Puppeteer WSAppShell/1.5.0 WebSpatial/1.5.0',
62
+ } as Navigator)
63
+ const { supports, resetRuntimeCacheForTests } = await import('./supports')
64
+ resetRuntimeCacheForTests()
65
+ expect(supports('useAnimation')).toBe(true)
66
+ })
67
+
68
+ test('visionOS WS_SHELL_VERSION placeholder: supports("useAnimation") is true (debug mode)', async () => {
69
+ vi.stubGlobal('navigator', {
70
+ userAgent:
71
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7; wv) AppleWebKit/605.1.15 WSAppShell/WS_SHELL_VERSION WebSpatial/1.5.0 Safari/537.36',
72
+ } as Navigator)
73
+ const { supports, resetRuntimeCacheForTests } = await import('./supports')
74
+ resetRuntimeCacheForTests()
75
+ expect(supports('useAnimation')).toBe(true)
76
+ })
77
+
78
+ test('picoOS PicoWebApp/0.2.2: supports("useAnimation") is false', async () => {
79
+ vi.stubGlobal('navigator', {
80
+ userAgent:
81
+ 'Mozilla/5.0 (X11; Linux x86_64; unknown OS0.11.0 like Quest) AppleWebKit/537.36 PicoWebApp/0.2.2 (like PicoBrowser) Chrome/138.0 WebSpatial/1.5.0',
82
+ } as Navigator)
83
+ const { supports, resetRuntimeCacheForTests } = await import('./supports')
84
+ resetRuntimeCacheForTests()
85
+ expect(supports('useAnimation')).toBe(false)
86
+ })
87
+
88
+ test('picoOS PicoWebApp/0.3.1: supports("useAnimation") is false', async () => {
89
+ vi.stubGlobal('navigator', {
90
+ userAgent:
91
+ 'Mozilla/5.0 (X11; Linux x86_64; unknown OS0.11.0 like Quest) AppleWebKit/537.36 PicoWebApp/0.3.1 (like PicoBrowser) Chrome/138.0 WebSpatial/1.5.0',
92
+ } as Navigator)
93
+ const { supports, resetRuntimeCacheForTests } = await import('./supports')
94
+ resetRuntimeCacheForTests()
95
+ expect(supports('useAnimation')).toBe(false)
96
+ })
97
+
98
+ test('picoOS PicoWebApp/0.4.90: supports("useAnimation") is true', async () => {
99
+ vi.stubGlobal('navigator', {
100
+ userAgent:
101
+ 'Mozilla/5.0 (X11; Linux x86_64; unknown OS0.11.0 like Quest) AppleWebKit/537.36 PicoWebApp/0.4.90 (like PicoBrowser) Chrome/138.0 WebSpatial/1.5.0',
102
+ } as Navigator)
103
+ const { supports, resetRuntimeCacheForTests } = await import('./supports')
104
+ resetRuntimeCacheForTests()
105
+ expect(supports('useAnimation')).toBe(true)
106
+ })
107
+ })
108
+
109
+ describe('supports("useAnimation", target tokens)', () => {
110
+ beforeEach(() => {
111
+ vi.resetModules()
112
+ })
113
+
114
+ test('plain browser: supports("useAnimation") and target tokens are false', async () => {
115
+ vi.stubGlobal('navigator', {
116
+ userAgent:
117
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36',
118
+ } as Navigator)
119
+ const { supports, resetRuntimeCacheForTests } = await import('./supports')
120
+ resetRuntimeCacheForTests()
121
+ expect(supports('useAnimation')).toBe(false)
122
+ expect(supports('useAnimation', ['entity'])).toBe(false)
123
+ expect(supports('useAnimation', ['element'])).toBe(false)
124
+ expect(supports('useAnimation', ['static3d'])).toBe(false)
125
+ expect(supports('useAnimation', ['dynamic3d'])).toBe(false)
126
+ })
127
+
128
+ test('visionOS WSAppShell/1.5.0: supports("useAnimation") and target tokens are false', async () => {
129
+ vi.stubGlobal('navigator', {
130
+ userAgent:
131
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 WSAppShell/1.5.0 WebSpatial/1.5.0',
132
+ } as Navigator)
133
+ const { supports, resetRuntimeCacheForTests } = await import('./supports')
134
+ resetRuntimeCacheForTests()
135
+ expect(supports('useAnimation')).toBe(false)
136
+ expect(supports('useAnimation', ['entity'])).toBe(false)
137
+ expect(supports('useAnimation', ['element'])).toBe(false)
138
+ expect(supports('useAnimation', ['static3d'])).toBe(false)
139
+ expect(supports('useAnimation', ['dynamic3d'])).toBe(false)
140
+ })
141
+
142
+ test('visionOS WSAppShell/1.6.0: supports("useAnimation") and target tokens are false', async () => {
143
+ vi.stubGlobal('navigator', {
144
+ userAgent:
145
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7; wv) AppleWebKit/605.1.15 (KHTML, like Gecko) WSAppShell/1.6.0 WebSpatial/1.5.0 Safari/537.36',
146
+ } as Navigator)
147
+ const { supports, resetRuntimeCacheForTests } = await import('./supports')
148
+ resetRuntimeCacheForTests()
149
+ expect(supports('useAnimation')).toBe(false)
150
+ expect(supports('useAnimation', ['entity'])).toBe(false)
151
+ expect(supports('useAnimation', ['element'])).toBe(false)
152
+ expect(supports('useAnimation', ['static3d'])).toBe(false)
153
+ expect(supports('useAnimation', ['dynamic3d'])).toBe(false)
154
+ })
155
+
156
+ test('Puppeteer UA: supports("useAnimation") is true while all sub-tokens are false', async () => {
157
+ vi.stubGlobal('navigator', {
158
+ userAgent:
159
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 Puppeteer WSAppShell/1.5.0 WebSpatial/1.5.0',
160
+ } as Navigator)
161
+ const { supports, resetRuntimeCacheForTests } = await import('./supports')
162
+ resetRuntimeCacheForTests()
163
+ expect(supports('useAnimation')).toBe(true)
164
+ expect(supports('useAnimation', ['entity'])).toBe(false)
165
+ expect(supports('useAnimation', ['element'])).toBe(false)
166
+ expect(supports('useAnimation', ['static3d'])).toBe(false)
167
+ expect(supports('useAnimation', ['dynamic3d'])).toBe(false)
168
+ })
169
+
170
+ test('visionOS WS_SHELL_VERSION placeholder: supports("useAnimation") is true while all sub-tokens are false', async () => {
171
+ vi.stubGlobal('navigator', {
172
+ userAgent:
173
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7; wv) AppleWebKit/605.1.15 WSAppShell/WS_SHELL_VERSION WebSpatial/1.5.0 Safari/537.36',
174
+ } as Navigator)
175
+ const { supports, resetRuntimeCacheForTests } = await import('./supports')
176
+ resetRuntimeCacheForTests()
177
+ expect(supports('useAnimation')).toBe(true)
178
+ expect(supports('useAnimation', ['entity'])).toBe(false)
179
+ expect(supports('useAnimation', ['element'])).toBe(false)
180
+ expect(supports('useAnimation', ['static3d'])).toBe(false)
181
+ expect(supports('useAnimation', ['dynamic3d'])).toBe(false)
182
+ })
183
+
184
+ test('picoOS PicoWebApp/0.1.1: supports("useAnimation") and target tokens are false', async () => {
185
+ vi.stubGlobal('navigator', {
186
+ userAgent:
187
+ 'Mozilla/5.0 (X11; Linux x86_64; unknown OS0.11.0 like Quest) AppleWebKit/537.36 PicoWebApp/0.1.1 (like PicoBrowser) Chrome/138.0 WebSpatial/1.5.0',
188
+ } as Navigator)
189
+ const { supports, resetRuntimeCacheForTests } = await import('./supports')
190
+ resetRuntimeCacheForTests()
191
+ expect(supports('useAnimation')).toBe(false)
192
+ expect(supports('useAnimation', ['entity'])).toBe(false)
193
+ expect(supports('useAnimation', ['element'])).toBe(false)
194
+ expect(supports('useAnimation', ['static3d'])).toBe(false)
195
+ expect(supports('useAnimation', ['dynamic3d'])).toBe(false)
196
+ })
197
+
198
+ test('picoOS PicoWebApp/0.1.2: supports("useAnimation") and target tokens are false', async () => {
199
+ vi.stubGlobal('navigator', {
200
+ userAgent:
201
+ 'Mozilla/5.0 (X11; Linux x86_64; unknown OS0.11.0 like Quest) AppleWebKit/537.36 PicoWebApp/0.1.2 (like PicoBrowser) Chrome/138.0 WebSpatial/1.5.0',
202
+ } as Navigator)
203
+ const { supports, resetRuntimeCacheForTests } = await import('./supports')
204
+ resetRuntimeCacheForTests()
205
+ expect(supports('useAnimation')).toBe(false)
206
+ expect(supports('useAnimation', ['entity'])).toBe(false)
207
+ expect(supports('useAnimation', ['element'])).toBe(false)
208
+ expect(supports('useAnimation', ['static3d'])).toBe(false)
209
+ expect(supports('useAnimation', ['dynamic3d'])).toBe(false)
210
+ })
211
+
212
+ test('picoOS PicoWebApp/0.2.2: supports("useAnimation") and all sub-tokens are false', async () => {
213
+ vi.stubGlobal('navigator', {
214
+ userAgent:
215
+ 'Mozilla/5.0 (X11; Linux x86_64; unknown OS0.11.0 like Quest) AppleWebKit/537.36 PicoWebApp/0.2.2 (like PicoBrowser) Chrome/138.0 WebSpatial/1.5.0',
216
+ } as Navigator)
217
+ const { supports, resetRuntimeCacheForTests } = await import('./supports')
218
+ resetRuntimeCacheForTests()
219
+ expect(supports('useAnimation')).toBe(false)
220
+ expect(supports('useAnimation', ['entity'])).toBe(false)
221
+ expect(supports('useAnimation', ['element'])).toBe(false)
222
+ expect(supports('useAnimation', ['static3d'])).toBe(false)
223
+ expect(supports('useAnimation', ['dynamic3d'])).toBe(false)
224
+ })
225
+
226
+ test('visionOS WSAppShell/1.8.0: supports("useAnimation") is true while all sub-tokens are false', async () => {
227
+ vi.stubGlobal('navigator', {
228
+ userAgent:
229
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7; wv) AppleWebKit/605.1.15 (KHTML, like Gecko) WSAppShell/1.8.0 WebSpatial/1.5.0 Safari/537.36',
230
+ } as Navigator)
231
+ const { supports, resetRuntimeCacheForTests } = await import('./supports')
232
+ resetRuntimeCacheForTests()
233
+ expect(supports('useAnimation')).toBe(true)
234
+ expect(supports('useAnimation', ['entity'])).toBe(false)
235
+ expect(supports('useAnimation', ['element'])).toBe(false)
236
+ expect(supports('useAnimation', ['static3d'])).toBe(false)
237
+ expect(supports('useAnimation', ['dynamic3d'])).toBe(false)
238
+ })
239
+
240
+ test('visionOS WSAppShell/1.7.0: supports("useAnimation") and all sub-tokens are false', async () => {
241
+ vi.stubGlobal('navigator', {
242
+ userAgent:
243
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7; wv) AppleWebKit/605.1.15 (KHTML, like Gecko) WSAppShell/1.7.0 WebSpatial/1.5.0 Safari/537.36',
244
+ } as Navigator)
245
+ const { supports, resetRuntimeCacheForTests } = await import('./supports')
246
+ resetRuntimeCacheForTests()
247
+ expect(supports('useAnimation')).toBe(false)
248
+ expect(supports('useAnimation', ['entity'])).toBe(false)
249
+ expect(supports('useAnimation', ['element'])).toBe(false)
250
+ expect(supports('useAnimation', ['static3d'])).toBe(false)
251
+ expect(supports('useAnimation', ['dynamic3d'])).toBe(false)
252
+ })
253
+ })
254
+
255
+ describe('useAnimation sub-tokens', () => {
256
+ beforeEach(() => {
257
+ vi.resetModules()
258
+ })
259
+
260
+ test('all useAnimation sub-tokens return false', async () => {
261
+ vi.stubGlobal('navigator', {
262
+ userAgent:
263
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 Puppeteer WSAppShell/1.5.0 WebSpatial/1.5.0',
264
+ } as Navigator)
265
+ const { supports, resetRuntimeCacheForTests } = await import('./supports')
266
+ resetRuntimeCacheForTests()
267
+ expect(supports('useAnimation')).toBe(true)
268
+ expect(supports('useAnimation', ['entity'])).toBe(false)
269
+ expect(supports('useAnimation', ['element'])).toBe(false)
270
+ expect(supports('useAnimation', ['static3d'])).toBe(false)
271
+ expect(supports('useAnimation', ['dynamic3d'])).toBe(false)
272
+ expect(supports('useAnimation', ['unknown' as any])).toBe(false)
273
+ expect(supports('useAnimation', ['opacity' as any])).toBe(false)
274
+ })
275
+ })