@breakside/jskit 2022.23.0 → 2022.25.1

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 (94) 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/JS/JSAttributedString.js +139 -10
  7. package/Frameworks/Foundation.jsframework/JS/JSFileManager+Node.js +2 -2
  8. package/Frameworks/Foundation.jsframework/JS/JSParagraphStyle.js +71 -0
  9. package/Frameworks/Foundation.jsframework/JS/JSTextAttachment.js +1 -1
  10. package/Frameworks/Foundation.jsframework/JS/JSTextContainer.js +56 -29
  11. package/Frameworks/Foundation.jsframework/JS/JSTextFrame.js +2 -32
  12. package/Frameworks/Foundation.jsframework/JS/JSTextFramesetter.js +125 -22
  13. package/Frameworks/Foundation.jsframework/JS/JSTextLayoutManager.js +11 -3
  14. package/Frameworks/Foundation.jsframework/JS/JSTextLine.js +4 -3
  15. package/Frameworks/Foundation.jsframework/JS/JSTextRun.js +5 -3
  16. package/Frameworks/Foundation.jsframework/JS/JSTextTypesetter.js +41 -25
  17. package/Frameworks/Foundation.jsframework/JS/JSURL.js +3 -0
  18. package/Frameworks/Foundation.jsframework/JS/JSZip.js +97 -76
  19. package/Frameworks/Foundation.jsframework/JS/String+JS.js +35 -0
  20. package/Frameworks/Foundation.jsframework/JS/UnicodeChar.js +8 -0
  21. package/Frameworks/Foundation.jsframework/io.breakside.JSKit.Foundation-bundle.js +2 -2
  22. package/Frameworks/Foundation.jsframework/sources.json +3 -0
  23. package/Frameworks/SecurityKit.jsframework/Info.json +2 -2
  24. package/Frameworks/SecurityKit.jsframework/io.breakside.JSKit.SecurityKit-bundle.js +2 -2
  25. package/Info.json +2 -2
  26. package/Node/io.breakside.jskit-bundle.js +2 -2
  27. package/Node/jskit +1 -0
  28. package/Root/Frameworks/APIKit/Info.yaml +1 -1
  29. package/Root/Frameworks/APIKitTesting/Info.yaml +1 -1
  30. package/Root/Frameworks/AuthKit/Info.yaml +1 -1
  31. package/Root/Frameworks/CSSOM/Info.yaml +1 -1
  32. package/Root/Frameworks/ChartKit/CHAxis.js +5 -5
  33. package/Root/Frameworks/ChartKit/CHPieChart.js +1 -1
  34. package/Root/Frameworks/ChartKit/Info.yaml +1 -1
  35. package/Root/Frameworks/ConferenceKit/Info.yaml +1 -1
  36. package/Root/Frameworks/DBKit/Info.yaml +1 -1
  37. package/Root/Frameworks/DOM/Info.yaml +1 -1
  38. package/Root/Frameworks/Dispatch/Info.yaml +1 -1
  39. package/Root/Frameworks/FontKit/Info.yaml +1 -1
  40. package/Root/Frameworks/Foundation/Info.yaml +1 -1
  41. package/Root/Frameworks/Foundation/JSAttributedString.js +139 -10
  42. package/Root/Frameworks/Foundation/JSFileManager+Node.js +2 -2
  43. package/Root/Frameworks/Foundation/JSParagraphStyle.js +71 -0
  44. package/Root/Frameworks/Foundation/JSTextAttachment.js +1 -1
  45. package/Root/Frameworks/Foundation/JSTextContainer.js +56 -29
  46. package/Root/Frameworks/Foundation/JSTextFrame.js +2 -32
  47. package/Root/Frameworks/Foundation/JSTextFramesetter.js +125 -22
  48. package/Root/Frameworks/Foundation/JSTextLayoutManager.js +11 -3
  49. package/Root/Frameworks/Foundation/JSTextLine.js +4 -3
  50. package/Root/Frameworks/Foundation/JSTextRun.js +5 -3
  51. package/Root/Frameworks/Foundation/JSTextTypesetter.js +41 -25
  52. package/Root/Frameworks/Foundation/JSURL.js +3 -0
  53. package/Root/Frameworks/Foundation/JSZip.js +97 -76
  54. package/Root/Frameworks/Foundation/String+JS.js +35 -0
  55. package/Root/Frameworks/Foundation/UnicodeChar.js +8 -0
  56. package/Root/Frameworks/ImageKit/Info.yaml +1 -1
  57. package/Root/Frameworks/MediaKit/Info.yaml +1 -1
  58. package/Root/Frameworks/MediaKitUI/Info.yaml +1 -1
  59. package/Root/Frameworks/NotificationKit/Info.yaml +1 -1
  60. package/Root/Frameworks/PDFKit/Info.yaml +1 -1
  61. package/Root/Frameworks/QRKit/Info.yaml +1 -1
  62. package/Root/Frameworks/SearchKit/Info.yaml +1 -1
  63. package/Root/Frameworks/SecurityKit/Info.yaml +1 -1
  64. package/Root/Frameworks/ServerKit/Info.yaml +1 -1
  65. package/Root/Frameworks/ServerKitTesting/Info.yaml +1 -1
  66. package/Root/Frameworks/TestKit/Info.yaml +1 -1
  67. package/Root/Frameworks/UIKit/Info.yaml +1 -1
  68. package/Root/Frameworks/UIKit/UIBasicAnimation.js +1 -1
  69. package/Root/Frameworks/UIKit/UIHTMLApplication.js +53 -15
  70. package/Root/Frameworks/UIKit/UIHTMLContentEditableTextInputManager.js +36 -0
  71. package/Root/Frameworks/UIKit/UIHTMLDisplayServer.js +1 -1
  72. package/Root/Frameworks/UIKit/UIHTMLTextField.js +1 -1
  73. package/Root/Frameworks/UIKit/UIHTMLTextFrame.js +19 -91
  74. package/Root/Frameworks/UIKit/UIHTMLTextFramesetter.js +52 -9
  75. package/Root/Frameworks/UIKit/UIHTMLTextLine.js +95 -30
  76. package/Root/Frameworks/UIKit/UIHTMLTextRun.js +22 -9
  77. package/Root/Frameworks/UIKit/UIHTMLTextTypesetter.js +334 -459
  78. package/Root/Frameworks/UIKit/UIHTMLWindowServer.js +16 -0
  79. package/Root/Frameworks/UIKit/UIImageLayer.js +14 -7
  80. package/Root/Frameworks/UIKit/UILabel.js +2 -0
  81. package/Root/Frameworks/UIKit/UIScrollView.js +12 -0
  82. package/Root/Frameworks/UIKit/UISegmentedControl.js +6 -6
  83. package/Root/Frameworks/UIKit/UIState.js +8 -1
  84. package/Root/Frameworks/UIKit/UITextAttachmentView.js +1 -1
  85. package/Root/Frameworks/UIKit/UITextEditor.js +210 -25
  86. package/Root/Frameworks/UIKit/UITextField.js +58 -31
  87. package/Root/Frameworks/UIKit/UITextInput.js +3 -1
  88. package/Root/Frameworks/UIKit/UITextInputManager.js +2 -2
  89. package/Root/Frameworks/UIKit/UITextLayer.js +39 -26
  90. package/Root/Frameworks/UIKit/UITokenField.js +4 -4
  91. package/Root/Frameworks/UIKit/UIView.js +3 -1
  92. package/Root/Frameworks/UIKit/UIWindow.js +16 -3
  93. package/Root/Frameworks/UIKitTesting/Info.yaml +1 -1
  94. package/package.json +1 -1
@@ -1,6 +1,9 @@
1
1
  // #import "JSObject.js"
2
2
  // #import "Promise+JS.js"
3
3
  // #import "JSCRC32.js"
4
+ // #import "JSDate.js"
5
+ // #import "JSCalendar.js"
6
+ // #import "Deflate.js"
4
7
  "use strict";
5
8
 
6
9
  JSClass("JSZip", JSObject, {
@@ -14,61 +17,89 @@ JSClass("JSZip", JSObject, {
14
17
  offset: 0,
15
18
 
16
19
  addFile: function(file, completion, target){
20
+ return this.addFileInDirectory(file, "", {}, completion, target);
21
+ },
22
+
23
+ addFileInDirectory: function(file, directory, attributes, completion, target){
17
24
  if (!completion){
18
25
  completion = Promise.completion(Promise.resolveNull);
19
26
  }
27
+ if (directory.startsWith("/")){
28
+ directory = directory.substr(1);
29
+ }
30
+ if (directory.length > 1 && !directory.endsWith("/")){
31
+ directory = directory + "/";
32
+ }
20
33
  file.readData(function(data){
21
34
  if (data === null){
22
35
  completion.call(target, new Error("Failed to read file data"));
23
36
  return;
24
37
  }
25
- this.addDataForFilename(data, file.name, completion, target);
38
+ var error = null;
39
+ try{
40
+ this.addDataForFilename(data, directory + file.name, attributes);
41
+ }catch (e){
42
+ error = e;
43
+ }
44
+ completion.call(target, error);
26
45
  }, this);
27
46
  return completion.promise;
28
47
  },
29
48
 
30
- addDataForFilename: function(data, name, completion, target){
31
- if (!completion){
32
- completion = Promise.completion(Promise.resolveNull);
33
- }
34
- var error = null;
35
- try{
36
- var encodedName = name.utf8();
37
- var header = JSData.initWithLength(30 + encodedName.length);
38
- var dataView = header.dataView();
39
- var crc = JSCRC32(data);
40
- dataView.setUint32(0, 0x04034b50, true);
41
- dataView.setUint16(4, 20, true);
42
- dataView.setUint16(6, 0, true);
43
- dataView.setUint16(8, 0, true); // no compression
44
- dataView.setUint16(10, 0, true); // date
45
- dataView.setUint16(12, 0, true); // date
46
- dataView.setUint32(14, crc, true);
47
- dataView.setUint32(18, data.length, true);
48
- dataView.setUint32(22, data.length, true);
49
- dataView.setUint16(26, encodedName.length, true);
50
- dataView.setUint16(28, 0, true);
51
- encodedName.copyTo(header, 30);
52
- this.directory.push({
53
- name: name,
54
- offset: this.offset,
55
- header: header
56
- });
57
- this.addChunk(header);
58
- this.addChunk(data);
59
- }catch (e){
60
- error = e;
49
+ addDataForFilename: function(data, name, attributes, deflate){
50
+ var encodedName = name.utf8();
51
+ var header = JSData.initWithLength(30 + encodedName.length);
52
+ var dataView = header.dataView();
53
+ var crc = JSCRC32(data);
54
+ var dateComponents = JSCalendar.gregorian.componentsFromDate(JSCalendar.Unit.day | JSCalendar.Unit.month | JSCalendar.Unit.year | JSCalendar.Unit.hour | JSCalendar.Unit.minute | JSCalendar.Unit.second, attributes.updated !== undefined ? JSDate.initWithTimeIntervalSince1970(attributes.updated) : JSDate.now, JSTimeZone.local || JSTimeZone.utc);
55
+ var dosDate = ((dateComponents.year - 1980) << 9) | ((dateComponents.month) << 5) | (dateComponents.day);
56
+ var dosTime = ((dateComponents.hour) << 11) | ((dateComponents.minute) << 5) | (Math.floor(dateComponents.second / 2));
57
+ var storedData = data;
58
+ var method = 0;
59
+ if (deflate){
60
+ var stream = DeflateStream();
61
+ stream.input = data;
62
+ stream.output = JSData.initWithLength(data.length);
63
+ stream.deflate(true);
64
+ if (stream.state === DeflateStream.State.done){
65
+ storedData = stream.output.subdataInRange(JSRange(0, stream.outputOffset));
66
+ method = 8;
67
+ }
61
68
  }
62
- completion.call(target, error);
63
- return completion.promise;
69
+ // Local File Header (APPNOTE.txt 4.3.7)
70
+ // Everything is little-endian
71
+ dataView.setUint32(0, 0x04034b50, true); // signtature
72
+ dataView.setUint16(4, 0x0014, true); // version needed to extract (2.0)
73
+ dataView.setUint16(6, 0, true); // general purpose flags
74
+ dataView.setUint16(8, method, true); // compression method (0=none, 8=deflate)
75
+ dataView.setUint16(10, dosTime, true); // last modified time (MS-DOS)
76
+ dataView.setUint16(12, dosDate, true); // last modified date (MS-DOS)
77
+ dataView.setUint32(14, crc, true); // crc-32 (magic number 0xdebb20e3, preconditioned to 0xffffffff, post-conditioned by one's compliment)
78
+ dataView.setUint32(18, storedData.length, true); // compressed size
79
+ dataView.setUint32(22, data.length, true); // uncompressed size
80
+ dataView.setUint16(26, encodedName.length, true); // name length
81
+ dataView.setUint16(28, 0, true); // extra field length
82
+ encodedName.copyTo(header, 30); // name (NOT null-terminated)
83
+ this.directory.push({
84
+ name: name,
85
+ offset: this.offset,
86
+ header: header
87
+ });
88
+ this.chunks.push(header);
89
+ this.chunks.push(storedData);
90
+ this.offset += header.length + storedData.length;
91
+ this._data = null;
64
92
  },
65
93
 
66
- close: function(completion, target){
67
- if (!completion){
68
- completion = Promise.completion(Promise.resolveNull);
69
- }
70
- var error = null;
71
- try{
94
+ directory: null,
95
+
96
+ chunks: null,
97
+
98
+ data: JSReadOnlyProperty("_data", null),
99
+
100
+ getData: function(){
101
+ if (this._data === null){
102
+ var chunks = JSCopy(this.chunks);
72
103
  var i, l;
73
104
  var centralDirectoryOffset = this.offset;
74
105
  var centralDirectorySize = 0;
@@ -77,49 +108,39 @@ JSClass("JSZip", JSObject, {
77
108
  var dataView;
78
109
  var file;
79
110
  for (i = 0, l = this.directory.length; i < l; ++i){
111
+ // Central Directory File Header (APPNOTE.txt 4.3.12)
112
+ // Everything is little-endian
80
113
  file = this.directory[i];
81
114
  header = JSData.initWithLength(46 + (file.header.length - 30));
82
115
  dataView = header.dataView();
83
- dataView.setUint32(0, 0x02014b50, true);
84
- dataView.setUint16(4, 0, true);
85
- file.header.subdataInRange(JSRange(4, 26)).copyTo(header, 6);
86
- dataView.setUint16(32, 0, true);
87
- dataView.setUint16(34, 0, true);
88
- dataView.setUint16(36, 0, true);
89
- dataView.setUint32(38, 0, true);
90
- dataView.setUint32(42, file.offset, true);
91
- file.header.subdataInRange(JSRange(30, file.header.length - 30)).copyTo(header, 46);
116
+ dataView.setUint32(0, 0x02014b50, true); // signature
117
+ dataView.setUint16(4, 0x0314, true); // version made by (UNIX=3, 2.0)
118
+ file.header.subdataInRange(JSRange(4, 26)).copyTo(header, 6); // copy from local header
119
+ dataView.setUint16(32, 0, true); // commenet length
120
+ dataView.setUint16(34, 0, true); // disk number start
121
+ dataView.setUint16(36, 0, true); // internal file attributes
122
+ dataView.setUint32(38, 0, true); // external file attributes
123
+ dataView.setUint32(42, file.offset, true); // offset of local header relative to first disk
124
+ file.header.subdataInRange(JSRange(30, file.header.length - 30)).copyTo(header, 46); // name (ALWAYS forward slashes for directories)
92
125
  centralDirectorySize += header.length;
93
- this.addChunk(header);
126
+ chunks.push(header);
94
127
  }
128
+ // End of Central Directory Record (APPNOTE.txt 4.3.16)
129
+ // everything is little-endian
95
130
  var end = JSData.initWithLength(22);
96
131
  dataView = end.dataView();
97
- dataView.setUint32(0, 0x06054b50, true);
98
- dataView.setUint16(4, 0, true);
99
- dataView.setUint16(6, 0, true);
100
- dataView.setUint16(8, this.directory.length, true);
101
- dataView.setUint16(10, this.directory.length, true);
102
- dataView.setUint32(12, centralDirectorySize, true);
103
- dataView.setUint32(16, centralDirectoryOffset, true);
104
- dataView.setUint16(20, 0, true);
105
- this.addChunk(end);
106
- this._data = JSData.initWithChunks(this.chunks);
107
- }catch (e){
108
- error = e;
132
+ dataView.setUint32(0, 0x06054b50, true); // signature
133
+ dataView.setUint16(4, 0, true); // number of this disk
134
+ dataView.setUint16(6, 0, true); // number of the disk with the start of central directory
135
+ dataView.setUint16(8, this.directory.length, true); // number of central directory items on this disk
136
+ dataView.setUint16(10, this.directory.length, true); // number of central directory items total
137
+ dataView.setUint32(12, centralDirectorySize, true); // size of central directory
138
+ dataView.setUint32(16, centralDirectoryOffset, true); // offset to central directory with respect to starting disk
139
+ dataView.setUint16(20, 0, true); // zip file comemnt length
140
+ chunks.push(end);
141
+ this._data = JSData.initWithChunks(chunks);
109
142
  }
110
- completion.call(target, error);
111
- return completion.promise;
112
- },
113
-
114
- addChunk: function(chunk){
115
- this.chunks.push(chunk);
116
- this.offset += chunk.length;
117
- },
118
-
119
- directory: null,
120
-
121
- chunks: null,
122
-
123
- data: JSReadOnlyProperty("_data", null),
143
+ return this._data;
144
+ }
124
145
 
125
146
  });
@@ -244,6 +244,25 @@ Object.defineProperties(String.prototype, {
244
244
  }
245
245
  },
246
246
 
247
+ rangeForParagraphAtIndex: {
248
+ enumerable: false,
249
+ value: function String_rangeForParagraphAtIndex(index){
250
+ var iterator1 = this.userPerceivedCharacterIterator(index);
251
+ var startIndex = iterator1.range.location;
252
+ var iterator2 = UserPerceivedCharacterIterator(iterator1);
253
+ iterator1.decrement();
254
+ while (!iterator1.isParagraphBreak){
255
+ startIndex = iterator1.range.location;
256
+ iterator1.decrement();
257
+ }
258
+ while (!iterator2.isParagraphBreak){
259
+ iterator2.increment();
260
+ }
261
+ var endIndex = iterator2.range.end;
262
+ return JSRange(startIndex, endIndex - startIndex);
263
+ }
264
+ },
265
+
247
266
  // -------------------------------------------------------------------------
248
267
  // MARK: - Changing a String
249
268
 
@@ -1159,6 +1178,22 @@ Object.defineProperties(UserPerceivedCharacterIterator.prototype, {
1159
1178
  // can start with CR, we know the second character must be LF.
1160
1179
  return this._unicodeIterator.character.isLineBreak;
1161
1180
  }
1181
+ },
1182
+
1183
+ isParagraphBreak: {
1184
+ enumerable: true,
1185
+ configurable: false,
1186
+ get: function UserPerceivedCharacterIterator_isMandatoryLineBreak(){
1187
+ if (this._unicodeIterator.character === null){
1188
+ return true;
1189
+ }
1190
+ // Note that even though we're only checking the first character,
1191
+ // it will match the multi-char CRLF sequence, which is considered
1192
+ // to be a single user perceived character. In this case, only
1193
+ // the CR is checked, but since no other user perceived character
1194
+ // can start with CR, we know the second character must be LF.
1195
+ return this._unicodeIterator.character.isParagraphBreak;
1196
+ }
1162
1197
  }
1163
1198
 
1164
1199
  });
@@ -778,6 +778,14 @@ UnicodeChar.prototype = Object.create(Object.prototype, {
778
778
  Object.defineProperty(this, 'isLineBreak', {value: this.code === UnicodeChar.LineBreaks.newLine || this.code === UnicodeChar.LineBreaks.formFeed || this.code === UnicodeChar.LineBreaks.carriageReturn || this.code === UnicodeChar.LineBreaks.nextLine || this.code === UnicodeChar.LineBreaks.lineSeparator || this.code === UnicodeChar.LineBreaks.paragraphSeparator});
779
779
  return this.isLineBreak;
780
780
  }
781
+ },
782
+
783
+ isParagraphBreak: {
784
+ configurable: true,
785
+ get: function UnicodeChar_lazy_isParagraphBreak(){
786
+ Object.defineProperty(this, 'isParagraphBreak', {value: this.code === UnicodeChar.LineBreaks.newLine || this.code === UnicodeChar.LineBreaks.formFeed || this.code === UnicodeChar.LineBreaks.carriageReturn || this.code === UnicodeChar.LineBreaks.nextLine || this.code === UnicodeChar.LineBreaks.paragraphSeparator});
787
+ return this.isParagraphBreak;
788
+ }
781
789
  }
782
790
 
783
791
  });
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.ImageKit
3
- JSBundleVersion: 2022.23.0
3
+ JSBundleVersion: 2022.25.1
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: 2022.23.0
3
+ JSBundleVersion: 2022.25.1
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.MediaKitUI
3
- JSBundleVersion: 2022.23.0
3
+ JSBundleVersion: 2022.25.1
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: 2022.23.0
3
+ JSBundleVersion: 2022.25.1
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: 2022.23.0
3
+ JSBundleVersion: 2022.25.1
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: 2022.23.0
3
+ JSBundleVersion: 2022.25.1
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: 2022.23.0
3
+ JSBundleVersion: 2022.25.1
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: 2022.23.0
3
+ JSBundleVersion: 2022.25.1
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: 2022.23.0
3
+ JSBundleVersion: 2022.25.1
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: 2022.23.0
3
+ JSBundleVersion: 2022.25.1
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: 2022.23.0
3
+ JSBundleVersion: 2022.25.1
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: 2022.23.0
3
+ JSBundleVersion: 2022.25.1
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -88,7 +88,7 @@ JSClass('UIBasicAnimation', UIPropertyAnimation, {
88
88
  var progress = this.timingFunction(this._state.currentPercentage);
89
89
  this.isComplete = this._state.isComplete();
90
90
  this._updateContext[this._updateProperty] = this.interpolation(this._fromValue, this._toValue, progress);
91
- if (this._updateContext === this._layer.presentation && this._updateProperty === "bounds"){
91
+ if (this._updateContext === this._layer.presentation && (this._updateProperty === "bounds" || this._updateProperty === "imageFrame")){
92
92
  this._layer.setNeedsDisplay();
93
93
  }
94
94
  },
@@ -29,6 +29,7 @@ JSClass("UIHTMLApplication", UIApplication, {
29
29
  initWithBundle: function(bundle, windowServer){
30
30
  UIHTMLApplication.$super.initWithBundle.call(this, bundle, windowServer);
31
31
  this.domWindow = this.windowServer.domWindow;
32
+ this.rememberStateInPath = this.bundle.info.UIHTMLUseURLPathForState === true;
32
33
  },
33
34
 
34
35
  setup: function(completion, target){
@@ -69,7 +70,7 @@ JSClass("UIHTMLApplication", UIApplication, {
69
70
  if (options === undefined){
70
71
  options = {};
71
72
  }
72
- if (options.replacingApplication){
73
+ if (options.replacingApplication || url.scheme === "mailto" || url.scheme === "tel"){
73
74
  var application = this;
74
75
  var open = function(){
75
76
  application.domWindow.location.href = url.encodedString;
@@ -93,17 +94,15 @@ JSClass("UIHTMLApplication", UIApplication, {
93
94
  this.stop(reload);
94
95
  },
95
96
 
96
- baseURL: JSReadOnlyProperty('_baseURL'),
97
+ baseURL: JSReadOnlyProperty('_baseURL', null),
98
+ rememberStateInPath: false,
97
99
 
98
100
  setState: function(state){
99
- UIHTMLApplication.$super.setState.call(this, state);
100
- var url = JSURL.initWithURL(this.baseURL);
101
- if (state.path !== "/"){
102
- url.fragment = state.path;
103
- }
104
- if (!this._isHandlingHashChange){
105
- var href = url.encodedString;
106
- if (href != this.domWindow.location.href){
101
+ if (!state.isEqual(this.state)){
102
+ UIHTMLApplication.$super.setState.call(this, state);
103
+ if (!this._isHandlingBrowserStateChange){
104
+ var url = this.urlForState(state);
105
+ var href = url.encodedString;
107
106
  this.domWindow.history.pushState(null, null, url.encodedString);
108
107
  }
109
108
  }
@@ -111,11 +110,20 @@ JSClass("UIHTMLApplication", UIApplication, {
111
110
 
112
111
  setStateReplacingHTMLState: function(state){
113
112
  UIHTMLApplication.$super.setState.call(this, state);
113
+ var url = this.urlForState(state);
114
+ this.domWindow.history.replaceState(null, null, url.encodedString);
115
+ },
116
+
117
+ urlForState: function(state){
114
118
  var url = JSURL.initWithURL(this.baseURL);
115
- if (state.path !== "/"){
116
- url.fragment = state.path;
119
+ if (state.pathComponents.length > 1){
120
+ if (this.rememberStateInPath){
121
+ url.appendPathComponents(state.pathComponents.slice(1));
122
+ }else{
123
+ url.fragment = state.path;
124
+ }
117
125
  }
118
- this.domWindow.history.replaceState(null, null, url.encodedString);
126
+ return url;
119
127
  },
120
128
 
121
129
  addEventListeners: function(){
@@ -123,6 +131,7 @@ JSClass("UIHTMLApplication", UIApplication, {
123
131
  this.domWindow.addEventListener("unhandledrejection", this);
124
132
  this.domWindow.addEventListener("beforeunload", this);
125
133
  this.domWindow.addEventListener("hashchange", this);
134
+ this.domWindow.addEventListener("popstate", this);
126
135
  },
127
136
 
128
137
  handleEvent: function(e){
@@ -160,7 +169,10 @@ JSClass("UIHTMLApplication", UIApplication, {
160
169
  },
161
170
 
162
171
  _event_hashchange: function(e){
163
- this._isHandlingHashChange = true;
172
+ if (this.rememberStateInPath){
173
+ return;
174
+ }
175
+ this._isHandlingBrowserStateChange = true;
164
176
  try{
165
177
  var requestedURL = JSURL.initWithString(this.domWindow.location.href);
166
178
  var requestedFragment = requestedURL.fragment;
@@ -185,7 +197,33 @@ JSClass("UIHTMLApplication", UIApplication, {
185
197
  }
186
198
  this.setStateReplacingHTMLState(state);
187
199
  }finally{
188
- this._isHandlingHashChange = false;
200
+ this._isHandlingBrowserStateChange = false;
201
+ }
202
+ },
203
+
204
+ _event_popstate: function(e){
205
+ if (!this.rememberStateInPath){
206
+ return;
207
+ }
208
+ this._isHandlingBrowserStateChange = true;
209
+ try{
210
+ var requestedURL = JSURL.initWithString(this.domWindow.location.href);
211
+ var relativeURL = JSURL.initWithString(requestedURL.encodedStringRelativeTo(this._baseURL));
212
+ var requestedState = UIState.initWithPath(relativeURL.path);
213
+ var state = null;
214
+ if (this.delegate && this.delegate.applicationDidRequestState){
215
+ state = this.delegate.applicationDidRequestState(this, requestedState);
216
+ }
217
+ if (state === null || state === undefined){
218
+ state = this.state;
219
+ }
220
+ if (state.isEqual(requestedState)){
221
+ UIHTMLApplication.$super.setState.call(this, state);
222
+ }else{
223
+ this.setStateReplacingHTMLState(state);
224
+ }
225
+ }finally{
226
+ this._isHandlingBrowserStateChange = false;
189
227
  }
190
228
  },
191
229
 
@@ -155,6 +155,9 @@ JSClass('UIHTMLContentEditableTextInputManager', UITextInputManager, {
155
155
  var selection = this.textInputClient.textInputSelections()[0];
156
156
  var anchor = textFrame.domSelectionPointForCharacterAtIndex(selection.startLocation);
157
157
  var focus = textFrame.domSelectionPointForCharacterAtIndex(selection.insertionLocation);
158
+ if (anchor.offset < 0 || focus.offset < 0){
159
+ throw new Error("negative dom offset");
160
+ }
158
161
  domSelection.setBaseAndExtent(anchor.node, anchor.offset, focus.node, focus.offset);
159
162
  // logger.debug("setting dom selection: %d->%d", anchor.offset, focus.offset);
160
163
  if (domSelection.anchorNode){
@@ -274,9 +277,41 @@ JSClass('UIHTMLContentEditableTextInputManager', UITextInputManager, {
274
277
  },
275
278
 
276
279
  focus: function(e){
280
+ if (UIDevice.shared && UIDevice.shared.primaryPointerType === UIUserInterface.PointerType.touch){
281
+ if (this.textInputClient instanceof UIView){
282
+ this._cancelNullFirstResponder(this.textInputClient);
283
+ }
284
+ }
277
285
  },
278
286
 
279
287
  blur: function(e){
288
+ if (UIDevice.shared && UIDevice.shared.primaryPointerType === UIUserInterface.PointerType.touch){
289
+ if (this.textInputClient instanceof UIView){
290
+ if (this.textInputClient.window){
291
+ if (this.textInputClient.window.firstResponder === this.textInputClient){
292
+ this._scheduleNullFirstResponder(this.textInputClient);
293
+ }
294
+ }
295
+ }
296
+ }
297
+ },
298
+
299
+ _nullFirstResponderTimer: null,
300
+
301
+ _scheduleNullFirstResponder: function(view){
302
+ this._nullFirstResponderTimer = JSTimer.scheduledTimerWithInterval(0.2, function(){
303
+ this._nullFirstResponderTimer = null;
304
+ if (view.window && view.window.firstResponder === view){
305
+ view.window.firstResponder = null;
306
+ }
307
+ }, this);
308
+ },
309
+
310
+ _cancelNullFirstResponder: function(responder){
311
+ if (this._nullFirstResponderTimer){
312
+ this._nullFirstResponderTimer.invalidate();
313
+ this._nullFirstResponderTimer = null;
314
+ }
280
315
  },
281
316
 
282
317
  select: function(e){
@@ -784,6 +819,7 @@ JSTextLayoutManager.definePropertiesFromExtensions({
784
819
  container = this._textContainers[i];
785
820
  offset += container._textFrame.recalculateRange(offset);
786
821
  container._textFrame.recalculateSize();
822
+ container.framesetter._updateSizesAndPositionsOfLinesInFrame(container._textFrame);
787
823
  }
788
824
  }
789
825
 
@@ -477,7 +477,7 @@ JSClass("UIHTMLDisplayServer", UIDisplayServer, {
477
477
  this.layerRemoved(layer);
478
478
  }else{
479
479
  var context = this.contextsByObjectID[attachment.objectID];
480
- if (context !== null){
480
+ if (context){
481
481
  context.destroy();
482
482
  delete this.contextsByObjectID[attachment.objectID];
483
483
  }
@@ -738,7 +738,7 @@ JSClass("UIHTMLTextField", UIControl, {
738
738
  var selection;
739
739
  for (var i = selections.length - 1; i >= 0; --i){
740
740
  selection = selections[i];
741
- this.inputElement.setRangeText(replacement, selection.location, selection.end, "end");
741
+ this.inputElement.setRangeText(replacement, selection.range.location, selection.range.end, "end");
742
742
  }
743
743
  this._text = this.inputElement.value;
744
744
  this._sendChangeNotificaions();