@breakside/jskit 2026.2.1 → 2026.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 (43) hide show
  1. package/Frameworks/DOM.jsframework/Info.json +2 -2
  2. package/Frameworks/DOM.jsframework/io.breakside.JSKit.DOM-bundle.js +2 -2
  3. package/Frameworks/FontKit.jsframework/Info.json +2 -2
  4. package/Frameworks/FontKit.jsframework/io.breakside.JSKit.FontKit-bundle.js +2 -2
  5. package/Frameworks/Foundation.jsframework/Info.json +2 -2
  6. package/Frameworks/Foundation.jsframework/io.breakside.JSKit.Foundation-bundle.js +2 -2
  7. package/Frameworks/SecurityKit.jsframework/Info.json +2 -2
  8. package/Frameworks/SecurityKit.jsframework/io.breakside.JSKit.SecurityKit-bundle.js +2 -2
  9. package/Info.json +2 -2
  10. package/Node/io.breakside.jskit-bundle.js +2 -2
  11. package/Root/Frameworks/APIKit/Info.yaml +1 -1
  12. package/Root/Frameworks/APIKitTesting/Info.yaml +1 -1
  13. package/Root/Frameworks/AuthKit/Info.yaml +1 -1
  14. package/Root/Frameworks/CSSOM/Info.yaml +1 -1
  15. package/Root/Frameworks/ChartKit/Info.yaml +1 -1
  16. package/Root/Frameworks/ConferenceKit/Info.yaml +1 -1
  17. package/Root/Frameworks/DBKit/Info.yaml +1 -1
  18. package/Root/Frameworks/DOM/Info.yaml +1 -1
  19. package/Root/Frameworks/Dispatch/Info.yaml +1 -1
  20. package/Root/Frameworks/FontKit/Info.yaml +1 -1
  21. package/Root/Frameworks/Foundation/Info.yaml +1 -1
  22. package/Root/Frameworks/ImageKit/Info.yaml +1 -1
  23. package/Root/Frameworks/MediaKit/Info.yaml +1 -1
  24. package/Root/Frameworks/MediaKit/MKAsset+HTML.js +5 -0
  25. package/Root/Frameworks/MediaKit/QuickTime/MKQuickTime.js +37 -0
  26. package/Root/Frameworks/MediaKit/QuickTime/MKQuickTimeMedia.js +79 -4
  27. package/Root/Frameworks/MediaKitUI/Info.yaml +1 -1
  28. package/Root/Frameworks/NotificationKit/Info.yaml +1 -1
  29. package/Root/Frameworks/PDFKit/Info.yaml +1 -1
  30. package/Root/Frameworks/QRKit/Info.yaml +1 -1
  31. package/Root/Frameworks/SearchKit/Info.yaml +1 -1
  32. package/Root/Frameworks/SecurityKit/Info.yaml +1 -1
  33. package/Root/Frameworks/ServerKit/Info.yaml +1 -1
  34. package/Root/Frameworks/ServerKitTesting/Info.yaml +1 -1
  35. package/Root/Frameworks/TestKit/Info.yaml +1 -1
  36. package/Root/Frameworks/UIKit/Info.yaml +1 -1
  37. package/Root/Frameworks/UIKit/UIBasicAnimation.js +22 -1
  38. package/Root/Frameworks/UIKit/UIHTMLDisplayServerCanvasContext.js +1 -1
  39. package/Root/Frameworks/UIKit/UISlider.js +6 -0
  40. package/Root/Frameworks/UIKit/UITextEditor.js +3 -0
  41. package/Root/Frameworks/UIKit/UIWindowServer.js +3 -0
  42. package/Root/Frameworks/UIKitTesting/Info.yaml +1 -1
  43. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "JSBundleType": "framework",
3
3
  "JSBundleIdentifier": "io.breakside.JSKit.DOM",
4
- "JSBundleVersion": "2026.2.1",
4
+ "JSBundleVersion": "2026.4.0",
5
5
  "JSDevelopmentLanguage": "en",
6
6
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
7
7
  "JSBundleEnvironments": {
@@ -9,5 +9,5 @@
9
9
  "node": "DOM+Node.js"
10
10
  },
11
11
  "JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
12
- "GitRevision": "a5d9a8ccacabe466afd5d0db9fba33bba7941a6a"
12
+ "GitRevision": "16922bf35c07196168a6b3ae71c9b96ea53d1c19"
13
13
  }
@@ -3,7 +3,7 @@ JSBundle.bundles['io.breakside.JSKit.DOM'] = {
3
3
  "Info": {
4
4
  "JSBundleType": "framework",
5
5
  "JSBundleIdentifier": "io.breakside.JSKit.DOM",
6
- "JSBundleVersion": "2026.2.1",
6
+ "JSBundleVersion": "2026.4.0",
7
7
  "JSDevelopmentLanguage": "en",
8
8
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
9
9
  "JSBundleEnvironments": {
@@ -11,7 +11,7 @@ JSBundle.bundles['io.breakside.JSKit.DOM'] = {
11
11
  "node": "DOM+Node.js"
12
12
  },
13
13
  "JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
14
- "GitRevision": "a5d9a8ccacabe466afd5d0db9fba33bba7941a6a"
14
+ "GitRevision": "16922bf35c07196168a6b3ae71c9b96ea53d1c19"
15
15
  },
16
16
  "Resources": [],
17
17
  "ResourceLookup": {
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "JSBundleType": "framework",
3
3
  "JSBundleIdentifier": "io.breakside.JSKit.FontKit",
4
- "JSBundleVersion": "2026.2.1",
4
+ "JSBundleVersion": "2026.4.0",
5
5
  "JSDevelopmentLanguage": "en",
6
6
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
7
7
  "JSBundleEnvironments": {
8
8
  "html": "FontKit+HTML.js"
9
9
  },
10
10
  "JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
11
- "GitRevision": "a5d9a8ccacabe466afd5d0db9fba33bba7941a6a"
11
+ "GitRevision": "16922bf35c07196168a6b3ae71c9b96ea53d1c19"
12
12
  }
@@ -3,14 +3,14 @@ JSBundle.bundles['io.breakside.JSKit.FontKit'] = {
3
3
  "Info": {
4
4
  "JSBundleType": "framework",
5
5
  "JSBundleIdentifier": "io.breakside.JSKit.FontKit",
6
- "JSBundleVersion": "2026.2.1",
6
+ "JSBundleVersion": "2026.4.0",
7
7
  "JSDevelopmentLanguage": "en",
8
8
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
9
9
  "JSBundleEnvironments": {
10
10
  "html": "FontKit+HTML.js"
11
11
  },
12
12
  "JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
13
- "GitRevision": "a5d9a8ccacabe466afd5d0db9fba33bba7941a6a"
13
+ "GitRevision": "16922bf35c07196168a6b3ae71c9b96ea53d1c19"
14
14
  },
15
15
  "Resources": [],
16
16
  "ResourceLookup": {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "JSBundleType": "framework",
3
3
  "JSBundleIdentifier": "io.breakside.JSKit.Foundation",
4
- "JSBundleVersion": "2026.2.1",
4
+ "JSBundleVersion": "2026.4.0",
5
5
  "JSDevelopmentLanguage": "en",
6
6
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
7
7
  "JSBundleEnvironments": {
@@ -9,5 +9,5 @@
9
9
  "node": "Foundation+Node.js"
10
10
  },
11
11
  "JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
12
- "GitRevision": "a5d9a8ccacabe466afd5d0db9fba33bba7941a6a"
12
+ "GitRevision": "16922bf35c07196168a6b3ae71c9b96ea53d1c19"
13
13
  }
@@ -3,7 +3,7 @@ JSBundle.bundles['io.breakside.JSKit.Foundation'] = {
3
3
  "Info": {
4
4
  "JSBundleType": "framework",
5
5
  "JSBundleIdentifier": "io.breakside.JSKit.Foundation",
6
- "JSBundleVersion": "2026.2.1",
6
+ "JSBundleVersion": "2026.4.0",
7
7
  "JSDevelopmentLanguage": "en",
8
8
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
9
9
  "JSBundleEnvironments": {
@@ -11,7 +11,7 @@ JSBundle.bundles['io.breakside.JSKit.Foundation'] = {
11
11
  "node": "Foundation+Node.js"
12
12
  },
13
13
  "JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
14
- "GitRevision": "a5d9a8ccacabe466afd5d0db9fba33bba7941a6a"
14
+ "GitRevision": "16922bf35c07196168a6b3ae71c9b96ea53d1c19"
15
15
  },
16
16
  "Resources": [
17
17
  {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "JSBundleType": "framework",
3
3
  "JSBundleIdentifier": "io.breakside.JSKit.SecurityKit",
4
- "JSBundleVersion": "2026.2.1",
4
+ "JSBundleVersion": "2026.4.0",
5
5
  "JSDevelopmentLanguage": "en",
6
6
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
7
7
  "JSBundleEnvironments": {
@@ -9,5 +9,5 @@
9
9
  "node": "SecurityKit+Node.js"
10
10
  },
11
11
  "JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
12
- "GitRevision": "a5d9a8ccacabe466afd5d0db9fba33bba7941a6a"
12
+ "GitRevision": "16922bf35c07196168a6b3ae71c9b96ea53d1c19"
13
13
  }
@@ -3,7 +3,7 @@ JSBundle.bundles['io.breakside.JSKit.SecurityKit'] = {
3
3
  "Info": {
4
4
  "JSBundleType": "framework",
5
5
  "JSBundleIdentifier": "io.breakside.JSKit.SecurityKit",
6
- "JSBundleVersion": "2026.2.1",
6
+ "JSBundleVersion": "2026.4.0",
7
7
  "JSDevelopmentLanguage": "en",
8
8
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
9
9
  "JSBundleEnvironments": {
@@ -11,7 +11,7 @@ JSBundle.bundles['io.breakside.JSKit.SecurityKit'] = {
11
11
  "node": "SecurityKit+Node.js"
12
12
  },
13
13
  "JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
14
- "GitRevision": "a5d9a8ccacabe466afd5d0db9fba33bba7941a6a"
14
+ "GitRevision": "16922bf35c07196168a6b3ae71c9b96ea53d1c19"
15
15
  },
16
16
  "Resources": [],
17
17
  "ResourceLookup": {
package/Info.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "JSBundleType": "node",
3
3
  "JSBundleIdentifier": "io.breakside.jskit",
4
- "JSBundleVersion": "2026.2.1",
4
+ "JSBundleVersion": "2026.4.0",
5
5
  "JSExecutableName": "jskit",
6
6
  "NPMOrganization": "breakside",
7
7
  "JSResources": [
8
8
  "Tests/HTMLTestRunner.js",
9
9
  "Tests/NodeTestRunner.js"
10
10
  ],
11
- "GitRevision": "a5d9a8ccacabe466afd5d0db9fba33bba7941a6a"
11
+ "GitRevision": "16922bf35c07196168a6b3ae71c9b96ea53d1c19"
12
12
  }
@@ -3,14 +3,14 @@ JSBundle.bundles['io.breakside.jskit'] = {
3
3
  "Info": {
4
4
  "JSBundleType": "node",
5
5
  "JSBundleIdentifier": "io.breakside.jskit",
6
- "JSBundleVersion": "2026.2.1",
6
+ "JSBundleVersion": "2026.4.0",
7
7
  "JSExecutableName": "jskit",
8
8
  "NPMOrganization": "breakside",
9
9
  "JSResources": [
10
10
  "Tests/HTMLTestRunner.js",
11
11
  "Tests/NodeTestRunner.js"
12
12
  ],
13
- "GitRevision": "a5d9a8ccacabe466afd5d0db9fba33bba7941a6a"
13
+ "GitRevision": "16922bf35c07196168a6b3ae71c9b96ea53d1c19"
14
14
  },
15
15
  "Resources": [
16
16
  {
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.APIKit
3
- JSBundleVersion: 2026.2.1
3
+ JSBundleVersion: 2026.4.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSIncludeDirectories:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.APIKitTesting
3
- JSBundleVersion: 2026.2.1
3
+ JSBundleVersion: 2026.4.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.AuthKit
3
- JSBundleVersion: 2026.2.1
3
+ JSBundleVersion: 2026.4.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.CSSOM
3
- JSBundleVersion: 2026.2.1
3
+ JSBundleVersion: 2026.4.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.ChartKit
3
- JSBundleVersion: 2026.2.1
3
+ JSBundleVersion: 2026.4.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2021 Breakside Inc.
6
6
  # JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.ConferenceKit
3
- JSBundleVersion: 2026.2.1
3
+ JSBundleVersion: 2026.4.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.DBKit
3
- JSBundleVersion: 2026.2.1
3
+ JSBundleVersion: 2026.4.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.DOM
3
- JSBundleVersion: 2026.2.1
3
+ JSBundleVersion: 2026.4.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.Dispatch
3
- JSBundleVersion: 2026.2.1
3
+ JSBundleVersion: 2026.4.0
4
4
  JSCopyright: Copyright © 2020 Breakside Inc.
5
5
  JSBundleEnvironments:
6
6
  html: Dispatch+HTML.js
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.FontKit
3
- JSBundleVersion: 2026.2.1
3
+ JSBundleVersion: 2026.4.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.Foundation
3
- JSBundleVersion: 2026.2.1
3
+ JSBundleVersion: 2026.4.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.ImageKit
3
- JSBundleVersion: 2026.2.1
3
+ JSBundleVersion: 2026.4.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.MediaKit
3
- JSBundleVersion: 2026.2.1
3
+ JSBundleVersion: 2026.4.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -73,6 +73,11 @@ MKAsset.definePropertiesFromExtensions({
73
73
  // logger.debug("drawn");
74
74
  canvas.toBlob(function(blob){
75
75
  // logger.debug("blob");
76
+ if (blob === null){
77
+ logger.error("Unable to get blob from canvas");
78
+ completion.call(target, null);
79
+ return;
80
+ }
76
81
  var reader = new FileReader();
77
82
  reader.addEventListener("loadend", function(){
78
83
  // logger.debug("read");
@@ -29,9 +29,43 @@ JSClass("MKQuickTime", MKQuickTimeAtom, {
29
29
  if (header === null){
30
30
  return -1;
31
31
  }
32
+ if (header.timeScale === 0){
33
+ logger.warn("mvhd timeScale = 0");
34
+ // Seen some videos in the wild with timeScale = 0
35
+ // That messes up our ability to calcualte things using timeScale,
36
+ // but those videos are still playable by QuickTime, so there's
37
+ // gotta be something else we can do. Documentation doesn't really
38
+ // say anything, so we'll look to tracks for an answer.
39
+ return this.durationCalculatedFromTracks;
40
+ }
32
41
  return header.duration / header.timeScale;
33
42
  },
34
43
 
44
+ durationCalculatedFromTracks: JSReadOnlyProperty(),
45
+
46
+ getDurationCalculatedFromTracks: function(){
47
+ var movie = this.movie;
48
+ if (movie === null){
49
+ return -1;
50
+ }
51
+ var track;
52
+ var media;
53
+ var i, l;
54
+ var longestTrackDuration = -1;
55
+ var duration;
56
+ for (i = 0, l = movie.tracks.length; i < l; ++i){
57
+ track = movie.tracks[i];
58
+ media = track.media;
59
+ if (media !== null){
60
+ duration = media.duration;
61
+ if (duration > longestTrackDuration){
62
+ longestTrackDuration = duration;
63
+ }
64
+ }
65
+ }
66
+ return longestTrackDuration;
67
+ },
68
+
35
69
  posterTime: JSReadOnlyProperty(),
36
70
 
37
71
  getPosterTime: function(){
@@ -43,6 +77,9 @@ JSClass("MKQuickTime", MKQuickTimeAtom, {
43
77
  if (header === null){
44
78
  return 0;
45
79
  }
80
+ if (header.timeScale === 0){
81
+ return 0;
82
+ }
46
83
  return header.posterTime / header.timeScale;
47
84
  },
48
85
 
@@ -38,6 +38,53 @@ JSClass("MKQuickTimeMedia", MKQuickTimeAtom, {
38
38
  return this.atomOfType(MKQuickTimeAtom.Type.hdlr);
39
39
  },
40
40
 
41
+ duration: JSReadOnlyProperty(),
42
+
43
+ getDuration: function(){
44
+ var header = this.mediaHeader;
45
+ if (header === null){
46
+ return -1;
47
+ }
48
+ if (header.timeScale === 0){
49
+ // Seen some videos in the wild with timeScale = 0
50
+ // That messes up our ability to calcualte things using timeScale,
51
+ // but those videos are still playable by QuickTime, so there's
52
+ // gotta be something else we can do. Documentation doesn't really
53
+ // say what to do, so we'll try to use sample counts and a guessed fps.
54
+ return this.durationCalculatedFromSamples;
55
+ }
56
+ return header.duration / header.timeScale;
57
+ },
58
+
59
+ durationCalculatedFromSamples: JSReadOnlyProperty(),
60
+
61
+ getDurationCalculatedFromSamples: function(){
62
+ var handler = this.mediaHandler;
63
+ if (handler === null){
64
+ return -1;
65
+ }
66
+ if (handler.componentSubtype !== MKQuickTimeMediaHandler.ComponentSubtype.vide){
67
+ return -1;
68
+ }
69
+ var info = this.mediaInformation;
70
+ if (info === null){
71
+ return -1;
72
+ }
73
+ var header = this.mediaHeader;
74
+ if (header === null){
75
+ return -1;
76
+ }
77
+ var counts = info.sampleCounts;
78
+ var totalCount = 0;
79
+ var i, l;
80
+ for (i = 0, l = counts.length; i < l; ++i){
81
+ totalCount += counts[i];
82
+ }
83
+ // We're only calling this method when timeScale is 0, in which case
84
+ // `averageVideoFrameRate` will be hard-coded to 30fps
85
+ return totalCount / this.averageVideoFrameRate;
86
+ },
87
+
41
88
  videoFrameRates: JSReadOnlyProperty(),
42
89
 
43
90
  getVideoFrameRates: function(){
@@ -59,8 +106,18 @@ JSClass("MKQuickTimeMedia", MKQuickTimeAtom, {
59
106
  var rates = [];
60
107
  var durations = info.sampleDurations;
61
108
  var i, l;
62
- for (i = 0, l = durations.length; i < l; ++i){
63
- rates.push(header.timeScale / durations[i]);
109
+ var timeScale = header.timeScale;
110
+ if (timeScale === 0){
111
+ // Seen some videos in the wild with timeScale = 0
112
+ // That messes up our ability to calcualte things using timeScale,
113
+ // but those videos are still playable by QuickTime, so there's
114
+ // gotta be something else we can do. Documentation doesn't really
115
+ // say what to do, so we'll go with a guess: 30fps.
116
+ rates.push(30);
117
+ }else{
118
+ for (i = 0, l = durations.length; i < l; ++i){
119
+ rates.push(timeScale / durations[i]);
120
+ }
64
121
  }
65
122
  return rates;
66
123
  },
@@ -83,6 +140,15 @@ JSClass("MKQuickTimeMedia", MKQuickTimeAtom, {
83
140
  if (header === null){
84
141
  return null;
85
142
  }
143
+ var timeScale = header.timeScale;
144
+ if (timeScale === 0){
145
+ // Seen some videos in the wild with timeScale = 0
146
+ // That messes up our ability to calcualte things using timeScale,
147
+ // but those videos are still playable by QuickTime, so there's
148
+ // gotta be something else we can do. Documentation doesn't really
149
+ // say what to do, so we'll go with a guess: 30fps.
150
+ return 30;
151
+ }
86
152
  var counts = info.sampleCounts;
87
153
  var durations = info.sampleDurations;
88
154
  var totalCount = 0;
@@ -90,7 +156,7 @@ JSClass("MKQuickTimeMedia", MKQuickTimeAtom, {
90
156
  var i, l;
91
157
  for (i = 0, l = durations.length; i < l; ++i){
92
158
  totalCount += counts[i];
93
- totalSeconds += (durations[i] * counts[i]) / header.timeScale;
159
+ totalSeconds += (durations[i] * counts[i]) / timeScale;
94
160
  }
95
161
  return totalCount / totalSeconds;
96
162
  },
@@ -141,6 +207,15 @@ JSClass("MKQuickTimeMedia", MKQuickTimeAtom, {
141
207
  if (sizeTable === null){
142
208
  return null;
143
209
  }
210
+ var timeScale = header.timeScale;
211
+ if (timeScale === 0){
212
+ // Seen some videos in the wild with timeScale = 0
213
+ // That messes up our ability to calcualte things using timeScale,
214
+ // but those videos are still playable by QuickTime, so there's
215
+ // gotta be something else we can do. Documentation doesn't really
216
+ // say what to do, so we'll just bail and say 0.
217
+ return 0;
218
+ }
144
219
  var counts = info.sampleCounts;
145
220
  var durations = info.sampleDurations;
146
221
  var totalSeconds = 0;
@@ -152,7 +227,7 @@ JSClass("MKQuickTimeMedia", MKQuickTimeAtom, {
152
227
  for (j = 0; j < counts[i]; ++j, ++s){
153
228
  totalBytes += sizeTable.sizeAtIndex(s);
154
229
  }
155
- totalSeconds += (durations[i] * counts[i]) / header.timeScale;
230
+ totalSeconds += (durations[i] * counts[i]) / timeScale;
156
231
  }
157
232
  return (totalBytes * 8) / totalSeconds;
158
233
  }
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.MediaKitUI
3
- JSBundleVersion: 2026.2.1
3
+ JSBundleVersion: 2026.4.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.NotificationKit
3
- JSBundleVersion: 2026.2.1
3
+ JSBundleVersion: 2026.4.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2021 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.PDFKit
3
- JSBundleVersion: 2026.2.1
3
+ JSBundleVersion: 2026.4.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.QRKit
3
- JSBundleVersion: 2026.2.1
3
+ JSBundleVersion: 2026.4.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.SearchKit
3
- JSBundleVersion: 2026.2.1
3
+ JSBundleVersion: 2026.4.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.SecurityKit
3
- JSBundleVersion: 2026.2.1
3
+ JSBundleVersion: 2026.4.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.ServerKit
3
- JSBundleVersion: 2026.2.1
3
+ JSBundleVersion: 2026.4.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.ServerKitTesting
3
- JSBundleVersion: 2026.2.1
3
+ JSBundleVersion: 2026.4.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.TestKit
3
- JSBundleVersion: 2026.2.1
3
+ JSBundleVersion: 2026.4.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.UIKit
3
- JSBundleVersion: 2026.2.1
3
+ JSBundleVersion: 2026.4.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -19,6 +19,8 @@
19
19
 
20
20
  (function(){
21
21
 
22
+ var logger = JSLog("uikit", "animation");
23
+
22
24
  JSClass('UIBasicAnimation', UIPropertyAnimation, {
23
25
  timingFunction: null,
24
26
  duration: JSDynamicProperty('_duration', 0.25),
@@ -87,7 +89,26 @@ JSClass('UIBasicAnimation', UIPropertyAnimation, {
87
89
  _updatePresentation: function(){
88
90
  var progress = this.timingFunction(this._state.currentPercentage);
89
91
  this.isComplete = this._state.isComplete();
90
- this._updateContext[this._updateProperty] = this.interpolation(this._fromValue, this._toValue, progress);
92
+ var value = this.interpolation(this._fromValue, this._toValue, progress);
93
+ if (this._updateContext === this._layer.presentation && this._updateProperty === "transform"){
94
+ if (value === undefined || value === null){
95
+ logger.debug("fromValue = %{public}, toValue = %{public}", "" + this._fromValue, "" + this._toValue);
96
+ if (this._layer.delegate instanceof UIView){
97
+ var view = this._layer.delegate;
98
+ logger.debug("view = %{public}, viewController = %{public}", view.$class.className, view.viewController ? view.viewController.$class.className : "null");
99
+ view = view.superview;
100
+ while (view !== null){
101
+ logger.debug("superview = %{public}, viewController = %{public}", view.$class.className, view.viewController ? view.viewController.$class.className : "null");
102
+ view = view.superview;
103
+ }
104
+ }else{
105
+ logger.debug("layer delegate is not a view");
106
+ }
107
+ logger.error("interpolated transform value is null/undefined");
108
+ value = JSAffineTransform.Identity;
109
+ }
110
+ }
111
+ this._updateContext[this._updateProperty] = value;
91
112
  if (this._updateContext === this._layer.presentation && (this._updateProperty === "bounds" || this._updateProperty === "imageFrame")){
92
113
  this._layer.setNeedsDisplay();
93
114
  }
@@ -283,7 +283,7 @@ JSClass("UIHTMLDisplayServerCanvasContext", UIHTMLDisplayServerContext, {
283
283
  updateHTMLProperty_transform: function(layer){
284
284
  var transform = layer.presentation.transform;
285
285
  var anchorPoint = layer.presentation.anchorPoint;
286
- if (!transform.isIdentity){
286
+ if (!!transform && !transform.isIdentity){
287
287
  var cssTransform = 'matrix(%f, %f, %f, %f, %f, %f)'.sprintf(transform.a, transform.b, transform.c, transform.d, transform.tx, transform.ty);
288
288
  this.style.transform = cssTransform;
289
289
  this.style.transformOrigin = '%f%% %f%% 0'.sprintf(anchorPoint.x * 100, anchorPoint.y * 100);
@@ -185,6 +185,9 @@ JSClass("UISlider", UIControl, {
185
185
  var p0 = this._cachedMinimumPoint;
186
186
  var p1 = this._cachedMaximumPoint;
187
187
  var length = p1.x - p0.x;
188
+ if (length <= 0){
189
+ return this._minimumValue;
190
+ }
188
191
  var dx = location.x - p0.x;
189
192
  return Math.min(this._maximumValue, Math.max(this._minimumValue, this._minimumValue + (this._maximumValue - this._minimumValue) * dx / length));
190
193
  },
@@ -194,6 +197,9 @@ JSClass("UISlider", UIControl, {
194
197
  var p0 = this._cachedMinimumPoint;
195
198
  var p1 = this._cachedMaximumPoint;
196
199
  var length = p1.x - p0.x;
200
+ if (length <= 0){
201
+ return JSPoint(p0);
202
+ }
197
203
  var dx = (value - this._minimumValue) / (this._maximumValue - this._minimumValue) * length;
198
204
  return JSPoint(p0.x + dx, p0.y);
199
205
  },
@@ -21,6 +21,8 @@
21
21
 
22
22
  (function(){
23
23
 
24
+ var logger = JSLog("uikit", "textedit");
25
+
24
26
  JSClass("UITextEditor", JSObject, {
25
27
 
26
28
  layoutLayer: null,
@@ -144,6 +146,7 @@ JSClass("UITextEditor", JSObject, {
144
146
  }
145
147
  }else{
146
148
  this._handledSelectOnMouseDown = true;
149
+ this._draggingSelectionIndex = 0;
147
150
  var range = null;
148
151
  var atomicRange;
149
152
  var affinity = UITextInput.SelectionAffinity.beforeCurrentCharacter;
@@ -871,6 +871,9 @@ JSClass("UIWindowServer", JSObject, {
871
871
  resizeView = window._resizeView;
872
872
  location = window.convertPointToView(location, resizeView);
873
873
  }
874
+ if (location === null){
875
+ return UIWindowServer.ResizeOperation.none;
876
+ }
874
877
  var resizeFrame = resizeView.bounds;
875
878
  var cornerSize = Math.max(resizeView.cornerRadius, this._windowResizeWidthInside);
876
879
  if (location.y < resizeFrame.origin.y - this._windowResizeWidthOutside){
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.UIKitTesting
3
- JSBundleVersion: 2026.2.1
3
+ JSBundleVersion: 2026.4.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
package/package.json CHANGED
@@ -12,7 +12,7 @@
12
12
  "node": ">=10.10.0"
13
13
  },
14
14
  "name": "@breakside/jskit",
15
- "version": "2026.2.1",
15
+ "version": "2026.4.0",
16
16
  "license": "SEE LICENSE IN LICENSE.txt",
17
17
  "files": [
18
18
  "*"