@breakside/jskit 2026.26.0 → 2026.27.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 (42) 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 +43 -0
  7. package/Frameworks/Foundation.jsframework/JS/JSPath.js +2 -0
  8. package/Frameworks/Foundation.jsframework/io.breakside.JSKit.Foundation-bundle.js +2 -2
  9. package/Frameworks/SecurityKit.jsframework/Info.json +2 -2
  10. package/Frameworks/SecurityKit.jsframework/io.breakside.JSKit.SecurityKit-bundle.js +2 -2
  11. package/Info.json +2 -2
  12. package/Node/io.breakside.jskit-bundle.js +2 -2
  13. package/Root/Frameworks/APIKit/Info.yaml +1 -1
  14. package/Root/Frameworks/APIKitTesting/Info.yaml +1 -1
  15. package/Root/Frameworks/AuthKit/Info.yaml +1 -1
  16. package/Root/Frameworks/CSSOM/CSSTokenizer.js +633 -470
  17. package/Root/Frameworks/CSSOM/Info.yaml +1 -1
  18. package/Root/Frameworks/ChartKit/Info.yaml +1 -1
  19. package/Root/Frameworks/ConferenceKit/Info.yaml +1 -1
  20. package/Root/Frameworks/DBKit/Info.yaml +1 -1
  21. package/Root/Frameworks/DOM/Info.yaml +1 -1
  22. package/Root/Frameworks/Dispatch/Info.yaml +1 -1
  23. package/Root/Frameworks/FontKit/Info.yaml +1 -1
  24. package/Root/Frameworks/Foundation/Info.yaml +1 -1
  25. package/Root/Frameworks/Foundation/JSAttributedString.js +43 -0
  26. package/Root/Frameworks/Foundation/JSPath.js +2 -0
  27. package/Root/Frameworks/ImageKit/Info.yaml +1 -1
  28. package/Root/Frameworks/MediaKit/Info.yaml +1 -1
  29. package/Root/Frameworks/MediaKitUI/Info.yaml +1 -1
  30. package/Root/Frameworks/NotificationKit/Info.yaml +1 -1
  31. package/Root/Frameworks/PDFKit/Info.yaml +1 -1
  32. package/Root/Frameworks/QRKit/Info.yaml +1 -1
  33. package/Root/Frameworks/SearchKit/Info.yaml +1 -1
  34. package/Root/Frameworks/SecurityKit/Info.yaml +1 -1
  35. package/Root/Frameworks/ServerKit/Info.yaml +1 -1
  36. package/Root/Frameworks/ServerKitTesting/Info.yaml +1 -1
  37. package/Root/Frameworks/TestKit/Info.yaml +1 -1
  38. package/Root/Frameworks/UIKit/Info.yaml +1 -1
  39. package/Root/Frameworks/UIKit/UITextEditor.js +17 -0
  40. package/Root/Frameworks/UIKit/UITextField.js +7 -0
  41. package/Root/Frameworks/UIKitTesting/Info.yaml +1 -1
  42. package/package.json +1 -1
@@ -20,609 +20,772 @@
20
20
 
21
21
  JSClass("CSSTokenizer", JSObject, {
22
22
 
23
- tokenize: function(input){
24
- var i = 0;
25
- var l = input.length;
26
- var isAtValidEscapeSequence = function(offset){
27
- if (offset === undefined){
28
- offset = 0;
29
- }
30
- var j = i + offset;
31
- return (j < l - 1) && input.charCodeAt(j) == 0x5C && !isNewline(input.charCodeAt(j + 1));
32
- };
33
- var isAtIdentifierStart = function(offset){
34
- if (offset === undefined){
35
- offset = 0;
23
+ cssText: "",
24
+ offset: 0,
25
+ length: 0,
26
+
27
+ initWithCSSText: function(cssText){
28
+ this.cssText = cssText;
29
+ this.length = this.cssText.length;
30
+ },
31
+
32
+ isAtValidEscapeSequence: function(offset){
33
+ if (offset === undefined){
34
+ offset = 0;
35
+ }
36
+ var i = this.offset + offset;
37
+ return (i < this.length - 1) && this.cssText.charCodeAt(i) == 0x5C && !CSSTokenizer.isNewline(this.cssText.charCodeAt(i + 1));
38
+ },
39
+
40
+ isAtIdentifierStart: function(offset){
41
+ if (offset === undefined){
42
+ offset = 0;
43
+ }
44
+ var i = this.offset + offset;
45
+ if (i < this.length){
46
+ var c = this.cssText.charCodeAt(i);
47
+ if (CSSTokenizer.isIdentifierStart(c)){
48
+ return true;
36
49
  }
37
- var j = i + offset;
38
- if (j < l){
39
- var c = input.charCodeAt(j);
40
- if (isIdentifierStart(c)){
41
- return true;
42
- }
43
- if (c == 0x2D){
44
- if (j < l - 1){
45
- c = input.charCodeAt(j + 1);
46
- if (c == 0x2D || isIdentifierStart(c)){
47
- return true;
48
- }
49
- if (isAtValidEscapeSequence(1)){
50
- return true;
51
- }
52
- return false;
50
+ if (c == 0x2D){
51
+ if (i < this.length - 1){
52
+ c = this.cssText.charCodeAt(i + 1);
53
+ if (c == 0x2D || CSSTokenizer.isIdentifierStart(c)){
54
+ return true;
55
+ }
56
+ if (this.isAtValidEscapeSequence(1)){
57
+ return true;
53
58
  }
54
59
  return false;
55
60
  }
56
- if (isAtValidEscapeSequence()){
57
- return true;
58
- }
59
61
  return false;
60
62
  }
61
- return false;
62
- };
63
- var isAtNumber = function(offset){
64
- if (offset === undefined){
65
- offset = 0;
63
+ if (this.isAtValidEscapeSequence()){
64
+ return true;
66
65
  }
67
- var j = i + offset;
68
- if (j < l){
69
- var c = input.charCodeAt(j);
70
- if (c == 0x2B || c == 0x2D){
71
- if (j < l - 1 && isDigit(input.charCodeAt(j + 1))){
72
- return true;
73
- }
74
- return j < l - 2 && input.charCodeAt(j + 1) == 0x2E && isDigit(input.charCodeAt(j + 2));
75
- }else if (c == 0x2E){
76
- return j < l - 1 && isDigit(input.charCodeAt(j + 1));
77
- }else if (isDigit(c)){
66
+ return false;
67
+ }
68
+ return false;
69
+ },
70
+
71
+ isAtNumber: function(offset){
72
+ if (offset === undefined){
73
+ offset = 0;
74
+ }
75
+ var i = this.offset + offset;
76
+ if (i < this.length){
77
+ var c = this.cssText.charCodeAt(i);
78
+ if (c == 0x2B || c == 0x2D){
79
+ if (i < this.length - 1 && CSSTokenizer.isDigit(this.cssText.charCodeAt(i + 1))){
78
80
  return true;
79
81
  }
82
+ return i < this.length - 2 && this.cssText.charCodeAt(i + 1) == 0x2E && CSSTokenizer.isDigit(this.cssText.charCodeAt(i + 2));
83
+ }else if (c == 0x2E){
84
+ return i < this.length - 1 && CSSTokenizer.isDigit(this.cssText.charCodeAt(i + 1));
85
+ }else if (CSSTokenizer.isDigit(c)){
86
+ return true;
80
87
  }
81
- return false;
82
- };
83
- var consumeEscapedCodePoint = function(){
84
- ++i;
85
- var i0 = i;
86
- if (i < l){
87
- var c = input.charCodeAt(i);
88
- if (isHexDigit(c)){
89
- ++i;
90
- while (i < l && i < i0 + 6 && isHexDigit(input.charCodeAt(i))){
91
- ++i;
92
- }
93
- var n = parseInt(input.substring(i0, i), 16);
94
- if (isWhitespace(input.charCodeAt(i))){
95
- ++i;
96
- }
97
- if (n === 0 || n > 0x10FFFF || (n >= 0xD800 && n <= 0xDFFF)){
98
- return 0xFFFD;
99
- }
100
- return String.fromCodePoint(n);
101
- }else{
102
- return input[i++];
88
+ }
89
+ return false;
90
+ },
91
+
92
+ consumeEscapedCodePoint: function(){
93
+ ++this.offset;
94
+ var i0 = this.offset;
95
+ if (this.offset < this.length){
96
+ var c = this.cssText.charCodeAt(this.offset);
97
+ if (CSSTokenizer.isHexDigit(c)){
98
+ ++this.offset;
99
+ while (this.offset < this.length && this.offset < i0 + 6 && CSSTokenizer.isHexDigit(this.cssText.charCodeAt(this.offset))){
100
+ ++this.offset;
103
101
  }
104
- }
105
- throw new Error("Found end of document in esape sequence");
106
- };
107
- var consumeIdentifier = function(){
108
- var value = "";
109
- var c;
110
- while (i < l){
111
- c = input.charCodeAt(i);
112
- if (isIdentifier(c)){
113
- value += input[i];
114
- ++i;
115
- }else if (isAtValidEscapeSequence()){
116
- value += consumeEscapedCodePoint();
117
- }else{
118
- return value;
102
+ var n = parseInt(this.cssText.substring(i0, this.offset), 16);
103
+ if (CSSTokenizer.isWhitespace(this.cssText.charCodeAt(this.offset))){
104
+ ++this.offset;
105
+ }
106
+ if (n === 0 || n > 0x10FFFF || (n >= 0xD800 && n <= 0xDFFF)){
107
+ return 0xFFFD;
119
108
  }
109
+ return String.fromCodePoint(n);
110
+ }else{
111
+ return this.cssText[this.offset++];
120
112
  }
121
- return value;
122
- };
123
- var consumeNumber = function(){
124
- var type = "integer";
125
- var str = "";
126
- var c = input.charCodeAt(i);
127
- if (c == 0x2B || c == 0x2D){
128
- str += input[i];
129
- ++i;
113
+ }
114
+ throw new Error("Found end of document in esape sequence");
115
+ },
116
+
117
+ consumeIdentifier: function(){
118
+ var value = "";
119
+ var c;
120
+ while (this.offset < this.length){
121
+ c = this.cssText.charCodeAt(this.offset);
122
+ if (CSSTokenizer.isIdentifier(c)){
123
+ value += this.cssText[this.offset];
124
+ ++this.offset;
125
+ }else if (this.isAtValidEscapeSequence()){
126
+ value += this.consumeEscapedCodePoint();
127
+ }else{
128
+ return value;
130
129
  }
131
- while (i < l && isDigit(input.charCodeAt(i))){
132
- str += input[i];
133
- ++i;
130
+ }
131
+ return value;
132
+ },
133
+
134
+ consumeNumber: function(){
135
+ var type = "integer";
136
+ var str = "";
137
+ var c = this.cssText.charCodeAt(this.offset);
138
+ if (c == 0x2B || c == 0x2D){
139
+ str += this.cssText[this.offset];
140
+ ++this.offset;
141
+ }
142
+ while (this.offset < this.length && CSSTokenizer.isDigit(this.cssText.charCodeAt(this.offset))){
143
+ str += this.cssText[this.offset];
144
+ ++this.offset;
145
+ }
146
+ if (this.offset < this.length - 1){
147
+ if (this.cssText.charCodeAt(this.offset) == 0x2E && CSSTokenizer.isDigit(this.cssText.charCodeAt(this.offset + 1))){
148
+ type = "number";
149
+ str += this.cssText[this.offset];
150
+ ++this.offset;
151
+ while (this.offset < this.length && CSSTokenizer.isDigit(this.cssText.charCodeAt(this.offset))){
152
+ str += this.cssText[this.offset];
153
+ ++this.offset;
154
+ }
134
155
  }
135
- if (i < l - 1){
136
- if (input.charCodeAt(i) == 0x2E && isDigit(input.charCodeAt(i + 1))){
156
+ }
157
+ if (this.offset < this.length - 1){
158
+ if ((this.cssText.charCodeAt(this.offset) == 0x45) || (this.cssText.charCodeAt(this.offset) == 0x65)){
159
+ if (CSSTokenizer.isDigit(this.cssText.charCodeAt(this.offset + 1))){
137
160
  type = "number";
138
- str += input[i];
139
- ++i;
140
- while (i < l && isDigit(input.charCodeAt(i))){
141
- str += input[i];
142
- ++i;
161
+ str += this.cssText[this.offset];
162
+ ++this.offset;
163
+ while (CSSTokenizer.isDigit(this.cssText.charCodeAt(this.offset))){
164
+ str += this.cssText[this.offset];
165
+ ++this.offset;
143
166
  }
144
- }
145
- }
146
- if (i < l - 1){
147
- if ((input.charCodeAt(i) == 0x45) || (input.charCodeAt(i) == 0x65)){
148
- if (isDigit(input.charCodeAt(i + 1))){
149
- type = "number";
150
- str += input[i];
151
- ++i;
152
- while (isDigit(input.charCodeAt(i))){
153
- str += input[i];
154
- ++i;
155
- }
156
- }else if (i < l -2 && input.charCodeAt(i + 1) == 0x2E && isDigit(input.charCodeAt(i + 2))){
157
- type = "number";
158
- str += input[i];
159
- ++i;
160
- str += input[i];
161
- ++i;
162
- while (isDigit(input.charCodeAt(i))){
163
- str += input[i];
164
- ++i;
165
- }
167
+ }else if (this.offset < this.length -2 && this.cssText.charCodeAt(this.offset + 1) == 0x2E && CSSTokenizer.isDigit(this.cssText.charCodeAt(this.offset + 2))){
168
+ type = "number";
169
+ str += this.cssText[this.offset];
170
+ ++this.offset;
171
+ str += this.cssText[this.offset];
172
+ ++this.offset;
173
+ while (CSSTokenizer.isDigit(this.cssText.charCodeAt(this.offset))){
174
+ str += this.cssText[this.offset];
175
+ ++this.offset;
166
176
  }
167
177
  }
168
178
  }
169
- return {type: type, str: str};
170
- };
171
- var consumeNumeric = function(){
172
- var info = consumeNumber();
173
- var n;
174
- if (info.type === "integer"){
175
- n = parseInt(info.str);
176
- }else{
177
- n = parseFloat(info.str);
178
- }
179
- if (i < l){
180
- if (isAtIdentifierStart()){
181
- var units = consumeIdentifier();
182
- return new CSSTokenizer.DimensionToken(n, units);
183
- }
184
- var c = input.charCodeAt(i);
185
- if (c === 0x25){
186
- ++i;
187
- return new CSSTokenizer.PercentageToken(n);
188
- }
179
+ }
180
+ return {type: type, str: str};
181
+ },
182
+
183
+ consumeNumeric: function(){
184
+ var info = this.consumeNumber();
185
+ var n;
186
+ if (info.type === "integer"){
187
+ n = parseInt(info.str);
188
+ }else{
189
+ n = parseFloat(info.str);
190
+ }
191
+ if (this.offset < this.length){
192
+ if (this.isAtIdentifierStart()){
193
+ var units = this.consumeIdentifier();
194
+ return new CSSDimensionToken(n, units);
189
195
  }
190
- return new CSSTokenizer.NumberToken(n);
191
- };
192
- var consumeURL = function(){
193
- var url = "";
194
- var c;
195
- while (i < l && isWhitespace(input.charCodeAt(i))){
196
- ++i;
196
+ var c = this.cssText.charCodeAt(this.offset);
197
+ if (c === 0x25){
198
+ ++this.offset;
199
+ return new CSSPercentageToken(n);
197
200
  }
198
- while (i < l){
199
- c = input.charCodeAt(i);
200
- if (c == 0x29){
201
- ++i;
202
- return new CSSTokenizer.URLToken(url);
203
- }else if (isWhitespace(c)){
204
- ++i;
205
- while (i < l && isWhitespace(input.charCodeAt(i))){
206
- ++i;
207
- }
208
- if (i < l){
209
- if (input.charCodeAt(i) == 0x29){
210
- ++i;
211
- return new CSSTokenizer.URLToken(url);
212
- }
213
- throw new Error("Expecting ) to end url at %d".sprintf(i));
214
- }
215
- throw new Error("Found end of document before end of url");
216
- }else if (c == 0x22 || c == 0x27 || c == 0x28){
217
- throw new Error("Unexpected %s in url at %d".sprintf(input[i], i));
218
- }else if (c == 0x5C){
219
- if (isAtValidEscapeSequence()){
220
- url += consumeEscapedCodePoint();
221
- }else{
222
- throw new Error("Bad escape sequence in url at %d".sprintf(i));
201
+ }
202
+ return new CSSNumberToken(n);
203
+ },
204
+
205
+ consumeURL: function(){
206
+ var url = "";
207
+ var c;
208
+ while (this.offset < this.length && CSSTokenizer.isWhitespace(this.cssText.charCodeAt(this.offset))){
209
+ ++this.offset;
210
+ }
211
+ while (this.offset < this.length){
212
+ c = this.cssText.charCodeAt(this.offset);
213
+ if (c == 0x29){
214
+ ++this.offset;
215
+ return new CSSURLToken(url);
216
+ }else if (CSSTokenizer.isWhitespace(c)){
217
+ ++this.offset;
218
+ while (this.offset < this.length && CSSTokenizer.isWhitespace(this.cssText.charCodeAt(this.offset))){
219
+ ++this.offset;
220
+ }
221
+ if (this.offset < this.length){
222
+ if (this.cssText.charCodeAt(this.offset) == 0x29){
223
+ ++this.offset;
224
+ return new CSSURLToken(url);
223
225
  }
226
+ throw new Error("Expecting ) to end url at %d".sprintf(this.offset));
227
+ }
228
+ throw new Error("Found end of document before end of url");
229
+ }else if (c == 0x22 || c == 0x27 || c == 0x28){
230
+ throw new Error("Unexpected %s in url at %d".sprintf(this.cssText[this.offset], this.offset));
231
+ }else if (c == 0x5C){
232
+ if (this.isAtValidEscapeSequence()){
233
+ url += this.consumeEscapedCodePoint();
224
234
  }else{
225
- url += input[i];
226
- ++i;
235
+ throw new Error("Bad escape sequence in url at %d".sprintf(this.offset));
227
236
  }
237
+ }else{
238
+ url += this.cssText[this.offset];
239
+ ++this.offset;
228
240
  }
229
- throw new Error("Found end of document before end of url");
230
- };
231
- var consumeIdentifierLike = function(){
232
- var identifier = consumeIdentifier();
233
- if (i < l){
234
- var c = input.charCodeAt(i);
235
- var lower = identifier.toLowerCase();
236
- if (lower == "url" && c == 0x28){
237
- ++i;
238
- if (i < l && isWhitespace(input.charCodeAt(i))){
239
- ++i;
240
- if (i < l && isWhitespace(input.charCodeAt(i))){
241
- ++i;
242
- }
241
+ }
242
+ throw new Error("Found end of document before end of url");
243
+ },
244
+
245
+ consumeIdentifierLike: function(){
246
+ var identifier = this.consumeIdentifier();
247
+ if (this.offset < this.length){
248
+ var c = this.cssText.charCodeAt(this.offset);
249
+ var lower = identifier.toLowerCase();
250
+ if (lower == "url" && c == 0x28){
251
+ ++this.offset;
252
+ if (this.offset < this.length && CSSTokenizer.isWhitespace(this.cssText.charCodeAt(this.offset))){
253
+ ++this.offset;
254
+ if (this.offset < this.length && CSSTokenizer.isWhitespace(this.cssText.charCodeAt(this.offset))){
255
+ ++this.offset;
243
256
  }
244
- if (i < l){
245
- c = input.charCodeAt(i);
246
- if (isWhitespace(c) && i < l - 1){
247
- c = input.charCodeAt(i + 1);
248
- }
249
- if (c == 0x22 || c == 0x27){
250
- return new CSSTokenizer.FunctionToken(identifier);
251
- }
252
- return consumeURL();
257
+ }
258
+ if (this.offset < this.length){
259
+ c = this.cssText.charCodeAt(this.offset);
260
+ if (CSSTokenizer.isWhitespace(c) && this.offset < this.length - 1){
261
+ c = this.cssText.charCodeAt(this.offset + 1);
262
+ }
263
+ if (c == 0x22 || c == 0x27){
264
+ return new CSSFunctionToken(identifier);
253
265
  }
254
- }else if (c == 0x28){
255
- ++i;
256
- return new CSSTokenizer.FunctionToken(identifier);
266
+ return this.consumeURL();
257
267
  }
268
+ }else if (c == 0x28){
269
+ ++this.offset;
270
+ return new CSSFunctionToken(identifier);
258
271
  }
259
- return new CSSTokenizer.IdentifierToken(identifier);
260
- };
261
- var consume = function(){
262
- var i0 = i;
263
- var c = input.charCodeAt(i);
264
- var str;
265
- var quote;
266
- if (i < l - 1 && c == 0x2F && input.charCodeAt(i + 1) == 0x2A){
267
- i += 2;
268
- while (i < l - 1 && (input.charCodeAt(i) != 0x2A || input.charCodeAt(i + 1) != 0x2F)){
269
- ++i;
270
- }
271
- if (i < l - 1){
272
- i += 2;
273
- return new CSSTokenizer.CommentToken(input.substring(i0 + 2, i - 2));
274
- }
275
- throw new Error("Found end of document before end of comment");
276
- }else if (isWhitespace(c)){
277
- ++i;
278
- while (i < l && isWhitespace(input.charCodeAt(i))){
279
- ++i;
280
- }
281
- return new CSSTokenizer.WhitespaceToken(input.substring(i0, i));
282
- }else if (c == 0x22 || c == 0x27){
283
- quote = c;
284
- ++i;
285
- str = "";
286
- while (i < l){
287
- c = input.charCodeAt(i);
288
- if (c == quote){
289
- ++i;
290
- return new CSSTokenizer.StringToken(input[i0], str);
291
- }else if (isNewline(c)){
292
- throw new Error("String includes unescaped newline at %d".sprintf(i));
293
- }else if (c == 0x5C){
294
- ++i;
295
- if (i < l){
296
- c = input.charCodeAt(i);
297
- // check for CRLF before checking for just CR
298
- // (adjustment to spec algorithm because we're not
299
- // preprocessing away the CRLFs)
300
- if (c == 0x0D){
301
- ++i;
302
- if (i < l && input.charCodeAt(i) == 0x0A){
303
- ++i;
304
- }
305
- }else if (isNewline(c)){
306
- ++i;
307
- }else{
308
- str += input[i];
309
- ++i;
272
+ }
273
+ return new CSSIdentifierToken(identifier);
274
+ },
275
+
276
+ consume: function(){
277
+ var i0 = this.offset;
278
+ var c = this.cssText.charCodeAt(this.offset);
279
+ var str;
280
+ var quote;
281
+ if (this.offset < this.length - 1 && c == 0x2F && this.cssText.charCodeAt(this.offset + 1) == 0x2A){
282
+ this.offset += 2;
283
+ while (this.offset < this.length - 1 && (this.cssText.charCodeAt(this.offset) != 0x2A || this.cssText.charCodeAt(this.offset + 1) != 0x2F)){
284
+ ++this.offset;
285
+ }
286
+ if (this.offset < this.length - 1){
287
+ this.offset += 2;
288
+ return new CSSCommentToken(this.cssText.substring(i0 + 2, this.offset - 2));
289
+ }
290
+ throw new Error("Found end of document before end of comment");
291
+ }else if (CSSTokenizer.isWhitespace(c)){
292
+ ++this.offset;
293
+ while (this.offset < this.length && CSSTokenizer.isWhitespace(this.cssText.charCodeAt(this.offset))){
294
+ ++this.offset;
295
+ }
296
+ return new CSSWhitespaceToken(this.cssText.substring(i0, this.offset));
297
+ }else if (c == 0x22 || c == 0x27){
298
+ quote = c;
299
+ ++this.offset;
300
+ str = "";
301
+ while (this.offset < this.length){
302
+ c = this.cssText.charCodeAt(this.offset);
303
+ if (c == quote){
304
+ ++this.offset;
305
+ return new CSSStringToken(this.cssText[i0], str);
306
+ }else if (CSSTokenizer.isNewline(c)){
307
+ throw new Error("String includes unescaped newline at %d".sprintf(this.offset));
308
+ }else if (c == 0x5C){
309
+ ++this.offset;
310
+ if (this.offset < this.length){
311
+ c = this.cssText.charCodeAt(this.offset);
312
+ // check for CRLF before checking for just CR
313
+ // (adjustment to spec algorithm because we're not
314
+ // preprocessing away the CRLFs)
315
+ if (c == 0x0D){
316
+ ++this.offset;
317
+ if (this.offset < this.length && this.cssText.charCodeAt(this.offset) == 0x0A){
318
+ ++this.offset;
310
319
  }
320
+ }else if (CSSTokenizer.isNewline(c)){
321
+ ++this.offset;
322
+ }else{
323
+ str += this.cssText[this.offset];
324
+ ++this.offset;
311
325
  }
312
- }else{
313
- str += input[i];
314
- ++i;
315
326
  }
327
+ }else{
328
+ str += this.cssText[this.offset];
329
+ ++this.offset;
316
330
  }
317
- throw new Error("Found end of document before end of string");
318
- }else if (c == 0x23){
319
- ++i;
320
- if (i < l){
321
- c = input.charCodeAt(i);
322
- if (isIdentifier(c) || isAtValidEscapeSequence()){
323
- if (isAtIdentifierStart()){
324
- str = consumeIdentifier();
325
- return new CSSTokenizer.HashToken("id", str);
326
- }else{
327
- str = consumeIdentifier();
328
- return new CSSTokenizer.HashToken(null, str);
329
- }
331
+ }
332
+ throw new Error("Found end of document before end of string");
333
+ }else if (c == 0x23){
334
+ ++this.offset;
335
+ if (this.offset < this.length){
336
+ c = this.cssText.charCodeAt(this.offset);
337
+ if (CSSTokenizer.isIdentifier(c) || this.isAtValidEscapeSequence()){
338
+ if (this.isAtIdentifierStart()){
339
+ str = this.consumeIdentifier();
340
+ return new CSSHashToken("id", str);
330
341
  }else{
331
- return new CSSTokenizer.DelimToken("#");
342
+ str = this.consumeIdentifier();
343
+ return new CSSHashToken(null, str);
332
344
  }
333
345
  }else{
334
- return new CSSTokenizer.DelimToken("#");
335
- }
336
- }else if (c == 0x28){
337
- ++i;
338
- return new CSSTokenizer.OpenParenToken();
339
- }else if (c == 0x29){
340
- ++i;
341
- return new CSSTokenizer.CloseParenToken();
342
- }else if (c == 0x2B){
343
- if (isAtNumber()){
344
- return consumeNumeric();
345
- }
346
- ++i;
347
- return new CSSTokenizer.DelimToken("+");
348
- }else if (c == 0x2C){
349
- ++i;
350
- return new CSSTokenizer.CommaToken();
351
- }else if (c == 0x2D){
352
- if (isAtNumber()){
353
- return consumeNumeric();
354
- }
355
- if (i < l - 2 && input.charCodeAt(i + 1) == 0x2D && input.charCodeAt(i + 2) == 0x3E){
356
- i += 3;
357
- return new CSSTokenizer.CDCToken();
346
+ return new CSSDelimToken("#");
358
347
  }
359
- if (isAtIdentifierStart()){
360
- return consumeIdentifierLike();
361
- }
362
- ++i;
363
- return new CSSTokenizer.DelimToken("-");
364
- }else if (c == 0x2E){
365
- if (isAtNumber()){
366
- return consumeNumeric();
367
- }
368
- ++i;
369
- return new CSSTokenizer.DelimToken(".");
370
- }else if (c == 0x3A){
371
- ++i;
372
- return new CSSTokenizer.ColonToken();
373
- }else if (c == 0x3B){
374
- ++i;
375
- return new CSSTokenizer.SemicolonToken();
376
- }else if (c == 0x3C){
377
- ++i;
378
- if (i < l - 2 && input.charCodeAt(i) == 0x21 && input.charCodeAt(i + 1) == 0x2D && input.charCodeAt(i + 2) == 0x2D){
379
- i += 3;
380
- return new CSSTokenizer.CDOToken();
381
- }
382
- return new CSSTokenizer.DelimToken("<");
383
- }else if (c == 0x40){
384
- ++i;
385
- if (isAtIdentifierStart()){
386
- str = consumeIdentifier();
387
- return new CSSTokenizer.AtKeywordToken(str);
388
- }
389
- return new CSSTokenizer.DelimToken("@");
390
- }else if (c == 0x5B){
391
- ++i;
392
- return new CSSTokenizer.OpenSquareToken();
393
- }else if (c == 0x5C){
394
- if (isAtValidEscapeSequence()){
395
- return consumeIdentifierLike();
396
- }
397
- throw new Error("Bad escape sequence at %d".sprintf(i));
398
- }else if (c == 0x5D){
399
- ++i;
400
- return new CSSTokenizer.CloseSquareToken();
401
- }else if (c == 0x7B){
402
- ++i;
403
- return new CSSTokenizer.OpenCurlyToken();
404
- }else if (c == 0x7D){
405
- ++i;
406
- return new CSSTokenizer.CloseCurlyToken();
407
- }else if (isDigit(c)){
408
- return consumeNumeric();
409
- }else if (isIdentifierStart(c)){
410
- return consumeIdentifierLike();
411
348
  }else{
412
- str = input[i];
413
- ++i;
414
- return new CSSTokenizer.DelimToken(str);
349
+ return new CSSDelimToken("#");
350
+ }
351
+ }else if (c == 0x28){
352
+ ++this.offset;
353
+ return new CSSOpenParenToken();
354
+ }else if (c == 0x29){
355
+ ++this.offset;
356
+ return new CSSCloseParenToken();
357
+ }else if (c == 0x2B){
358
+ if (this.isAtNumber()){
359
+ return this.consumeNumeric();
360
+ }
361
+ ++this.offset;
362
+ return new CSSDelimToken("+");
363
+ }else if (c == 0x2C){
364
+ ++this.offset;
365
+ return new CSSCommaToken();
366
+ }else if (c == 0x2D){
367
+ if (this.isAtNumber()){
368
+ return this.consumeNumeric();
369
+ }
370
+ if (this.offset < this.length - 2 && this.cssText.charCodeAt(this.offset + 1) == 0x2D && this.cssText.charCodeAt(this.offset + 2) == 0x3E){
371
+ this.offset += 3;
372
+ return new CSSCDCToken();
373
+ }
374
+ if (this.isAtIdentifierStart()){
375
+ return this.consumeIdentifierLike();
376
+ }
377
+ ++this.offset;
378
+ return new CSSDelimToken("-");
379
+ }else if (c == 0x2E){
380
+ if (this.isAtNumber()){
381
+ return this.consumeNumeric();
415
382
  }
416
- };
383
+ ++this.offset;
384
+ return new CSSDelimToken(".");
385
+ }else if (c == 0x3A){
386
+ ++this.offset;
387
+ return new CSSColonToken();
388
+ }else if (c == 0x3B){
389
+ ++this.offset;
390
+ return new CSSSemicolonToken();
391
+ }else if (c == 0x3C){
392
+ ++this.offset;
393
+ if (this.offset < this.length - 2 && this.cssText.charCodeAt(this.offset) == 0x21 && this.cssText.charCodeAt(this.offset + 1) == 0x2D && this.cssText.charCodeAt(this.offset + 2) == 0x2D){
394
+ this.offset += 3;
395
+ return new CSSCDOToken();
396
+ }
397
+ return new CSSDelimToken("<");
398
+ }else if (c == 0x40){
399
+ ++this.offset;
400
+ if (this.isAtIdentifierStart()){
401
+ str = this.consumeIdentifier();
402
+ return new CSSAtKeywordToken(str);
403
+ }
404
+ return new CSSDelimToken("@");
405
+ }else if (c == 0x5B){
406
+ ++this.offset;
407
+ return new CSSOpenSquareToken();
408
+ }else if (c == 0x5C){
409
+ if (this.isAtValidEscapeSequence()){
410
+ return this.consumeIdentifierLike();
411
+ }
412
+ throw new Error("Bad escape sequence at %d".sprintf(this.offset));
413
+ }else if (c == 0x5D){
414
+ ++this.offset;
415
+ return new CSSCloseSquareToken();
416
+ }else if (c == 0x7B){
417
+ ++this.offset;
418
+ return new CSSOpenCurlyToken();
419
+ }else if (c == 0x7D){
420
+ ++this.offset;
421
+ return new CSSCloseCurlyToken();
422
+ }else if (CSSTokenizer.isDigit(c)){
423
+ return this.consumeNumeric();
424
+ }else if (CSSTokenizer.isIdentifierStart(c)){
425
+ return this.consumeIdentifierLike();
426
+ }else{
427
+ str = this.cssText[this.offset];
428
+ ++this.offset;
429
+ return new CSSDelimToken(str);
430
+ }
431
+ },
432
+
433
+ next: function(){
434
+ if (this.offset < this.length){
435
+ var token = this.consume();
436
+ return token;
437
+ }
438
+ return null;
439
+ },
440
+
441
+ tokenize: function(){
417
442
  var tokens = [];
418
- var token;
419
- while (i < l){
420
- token = consume();
443
+ var token = this.next();
444
+ while (token !== null){
421
445
  tokens.push(token);
446
+ token = this.next();
422
447
  }
423
448
  return tokens;
424
449
  }
425
450
 
426
451
  });
427
452
 
428
- var isUpperCase = function(code){
453
+ CSSTokenizer.isUpperCase = function(code){
429
454
  return (code >= 0x41 && code <= 0x5A);
430
455
  };
431
456
 
432
- var isLowerCase = function(code){
457
+ CSSTokenizer.isLowerCase = function(code){
433
458
  return (code >= 0x61 && code <= 0x7A);
434
459
  };
435
460
 
436
- var isDigit = function(code){
461
+ CSSTokenizer.isDigit = function(code){
437
462
  return (code >= 0x30 && code <= 0x39);
438
463
  };
439
464
 
440
- var isHexDigit = function(code){
441
- return isDigit(code) || (code >= 0x41 && code <= 0x46) || (code >= 0x61 && code <= 0x66);
465
+ CSSTokenizer.isHexDigit = function(code){
466
+ return CSSTokenizer.isDigit(code) || (code >= 0x41 && code <= 0x46) || (code >= 0x61 && code <= 0x66);
442
467
  };
443
468
 
444
- var isLetter = function(code){
445
- return isUpperCase(code) || isLowerCase(code);
469
+ CSSTokenizer.isLetter = function(code){
470
+ return CSSTokenizer.isUpperCase(code) || CSSTokenizer.isLowerCase(code);
446
471
  };
447
472
 
448
- var isNonASCII = function(code){
473
+ CSSTokenizer.isNonASCII = function(code){
449
474
  return code >= 0x80;
450
475
  };
451
476
 
452
- var isIdentifierStart = function(code){
453
- return isLetter(code) || isNonASCII(code) || code == 0x5F;
477
+ CSSTokenizer.isIdentifierStart = function(code){
478
+ return CSSTokenizer.isLetter(code) || CSSTokenizer.isNonASCII(code) || code == 0x5F;
454
479
  };
455
480
 
456
- var isIdentifier = function(code){
457
- return isIdentifierStart(code) || isDigit(code) || code == 0x2D;
481
+ CSSTokenizer.isIdentifier = function(code){
482
+ return CSSTokenizer.isIdentifierStart(code) || CSSTokenizer.isDigit(code) || code == 0x2D;
458
483
  };
459
484
 
460
- var isWhitespace = function(code){
485
+ CSSTokenizer.isWhitespace = function(code){
461
486
  return code == 0x20 || code == 0x09 || code == 0x0A || code == 0x0D || code == 0x0C;
462
487
  };
463
488
 
464
- var isNewline = function(code){
489
+ CSSTokenizer.isNewline = function(code){
465
490
  return code == 0x0A || code == 0x0D || code == 0x0C;
466
491
  };
467
492
 
468
- CSSTokenizer.CommentToken = function(text){
493
+ JSGlobalObject.CSSCommentToken = function CSSCommentToken(text){
469
494
  this.text = text;
470
- this.toString = function(){
471
- return "/*" + this.text + "*/";
472
- };
473
495
  };
474
496
 
475
- CSSTokenizer.IdentifierToken = function(name){
497
+ Object.defineProperties(CSSCommentToken.prototype, {
498
+ toString: {
499
+ enumerable: false,
500
+ value: function CSSCommentToken_toString(){
501
+ return "/*" + this.text + "*/";
502
+ }
503
+ }
504
+ });
505
+
506
+ JSGlobalObject.CSSIdentifierToken = function CSSIdentifierToken(name){
476
507
  this.name = name;
477
- this.toString = function(){
478
- // FIXME: escape sequences
479
- return this.name;
480
- };
481
508
  };
482
509
 
483
- CSSTokenizer.FunctionToken = function(name){
510
+ Object.defineProperties(CSSIdentifierToken.prototype, {
511
+ toString: {
512
+ enumerable: false,
513
+ value: function CSSIdentifierToken_toString(){
514
+ // FIXME: escape sequences
515
+ return this.name;
516
+ }
517
+ }
518
+ });
519
+
520
+ JSGlobalObject.CSSFunctionToken = function CSSFunctionToken(name){
484
521
  this.name = name;
485
- this.toString = function(){
486
- // FIXME: escape sequences
487
- return this.name + "(";
488
- };
489
522
  };
490
523
 
491
- CSSTokenizer.AtKeywordToken = function(name){
524
+ Object.defineProperties(CSSFunctionToken.prototype, {
525
+ toString: {
526
+ enumerable: false,
527
+ value: function CSSFunctionToken_toString(){
528
+ // FIXME: escape sequences
529
+ return this.name + "(";
530
+ }
531
+ }
532
+ });
533
+
534
+ JSGlobalObject.CSSAtKeywordToken = function CSSAtKeywordToken(name){
492
535
  this.name = name;
493
- this.toString = function(){
494
- // FIXME: escape sequences
495
- return "@" + this.name;
496
- };
497
536
  };
498
537
 
499
- CSSTokenizer.HashToken = function(type, name){
538
+ Object.defineProperties(CSSAtKeywordToken.prototype, {
539
+ toString: {
540
+ enumerable: false,
541
+ value: function CSSAtKeywordToken_toString(){
542
+ // FIXME: escape sequences
543
+ return "@" + this.name;
544
+ }
545
+ }
546
+ });
547
+
548
+ JSGlobalObject.CSSHashToken = function CSSHashToken(type, name){
500
549
  this.type = type;
501
550
  this.name = name;
502
- this.toString = function(){
503
- // FIXME: escape sequences
504
- return "#" + this.name;
505
- };
506
551
  };
507
552
 
508
- CSSTokenizer.StringToken = function(quote, value){
553
+ Object.defineProperties(CSSHashToken.prototype, {
554
+ toString: {
555
+ enumerable: false,
556
+ value: function CSSHashToken_toString(){
557
+ // FIXME: escape sequences
558
+ return "#" + this.name;
559
+ }
560
+ }
561
+ });
562
+
563
+ JSGlobalObject.CSSStringToken = function CSSStringToken(quote, value){
509
564
  this.quote = quote;
510
565
  this.value = value;
511
- this.toString = function(){
512
- // FIXME: escape sequences
513
- return this.quote + this.value.replace(this.quote, "\\" + this.quote) + this.quote;
514
- };
515
566
  };
516
567
 
517
- CSSTokenizer.URLToken = function(url){
568
+ Object.defineProperties(CSSStringToken.prototype, {
569
+ toString: {
570
+ enumerable: false,
571
+ value: function CSSStringToken_toString(){
572
+ // FIXME: escape sequences
573
+ return this.quote + this.value.replace(this.quote, "\\" + this.quote) + this.quote;
574
+ }
575
+ }
576
+ });
577
+
578
+ JSGlobalObject.CSSURLToken = function CSSURLToken(url){
518
579
  this.url = url;
519
- this.toString = function(){
520
- // FIXME: escape sequences
521
- return "url(" + this.url + ")";
522
- };
523
580
  };
524
581
 
525
- CSSTokenizer.WhitespaceToken = function(whitespace){
582
+ Object.defineProperties(CSSURLToken.prototype, {
583
+ toString: {
584
+ enumerable: false,
585
+ value: function CSSURLToken_toString(){
586
+ // FIXME: escape sequences
587
+ return "url(" + this.url + ")";
588
+ }
589
+ }
590
+ });
591
+
592
+ JSGlobalObject.CSSWhitespaceToken = function CSSWhitespaceToken(whitespace){
526
593
  this.whitespace = whitespace;
527
- this.toString = function(){
528
- return this.whitespace;
529
- };
530
594
  };
531
595
 
532
- CSSTokenizer.OpenParenToken = function(){
533
- this.toString = function(){
534
- return "(";
535
- };
596
+ Object.defineProperties(CSSWhitespaceToken.prototype, {
597
+ toString: {
598
+ enumerable: false,
599
+ value: function CSSWhitespaceToken_toString(){
600
+ return this.whitespace;
601
+ }
602
+ }
603
+ });
604
+
605
+ JSGlobalObject.CSSOpenParenToken = function CSSOpenParenToken(){
536
606
  };
537
607
 
538
- CSSTokenizer.CloseParenToken = function(){
539
- this.toString = function(){
540
- return ")";
541
- };
608
+ Object.defineProperties(CSSOpenParenToken.prototype, {
609
+ toString: {
610
+ enumerable: false,
611
+ value: function CSSOpenParenToken_toString(){
612
+ return "(";
613
+ }
614
+ }
615
+ });
616
+
617
+ JSGlobalObject.CSSCloseParenToken = function CSSCloseParenToken(){
542
618
  };
543
619
 
544
- CSSTokenizer.CommaToken = function(){
545
- this.toString = function(){
546
- return ",";
547
- };
620
+ Object.defineProperties(CSSCloseParenToken.prototype, {
621
+ toString: {
622
+ enumerable: false,
623
+ value: function CSSCloseParenToken_toString(){
624
+ return ")";
625
+ }
626
+ }
627
+ });
628
+
629
+ JSGlobalObject.CSSCommaToken = function CSSCommaToken(){
548
630
  };
549
631
 
550
- CSSTokenizer.ColonToken = function(){
551
- this.toString = function(){
552
- return ":";
553
- };
632
+ Object.defineProperties(CSSCommaToken.prototype, {
633
+ toString: {
634
+ enumerable: false,
635
+ value: function CSSCommaToken_toString(){
636
+ return ",";
637
+ }
638
+ }
639
+ });
640
+
641
+ JSGlobalObject.CSSColonToken = function CSSColonToken(){
554
642
  };
555
643
 
556
- CSSTokenizer.SemicolonToken = function(){
557
- this.toString = function(){
558
- return ";";
559
- };
644
+ Object.defineProperties(CSSColonToken.prototype, {
645
+ toString: {
646
+ enumerable: false,
647
+ value: function CSSColonToken_toString(){
648
+ return ":";
649
+ }
650
+ }
651
+ });
652
+
653
+ JSGlobalObject.CSSSemicolonToken = function CSSSemicolonToken(){
560
654
  };
561
655
 
562
- CSSTokenizer.DimensionToken = function(value, units){
656
+ Object.defineProperties(CSSSemicolonToken.prototype, {
657
+ toString: {
658
+ enumerable: false,
659
+ value: function CSSSemicolonToken_toString(){
660
+ return ";";
661
+ }
662
+ }
663
+ });
664
+
665
+ JSGlobalObject.CSSDimensionToken = function CSSDimensionToken(value, units){
563
666
  this.value = value;
564
667
  this.units = units;
565
- this.toString = function(){
566
- // FIXME: escape sequences units
567
- return this.value.toString() + this.units;
568
- };
569
668
  };
570
669
 
571
- CSSTokenizer.PercentageToken = function(value){
670
+ Object.defineProperties(CSSDimensionToken.prototype, {
671
+ toString: {
672
+ enumerable: false,
673
+ value: function CSSDimensionToken_toString(){
674
+ // FIXME: escape sequences units
675
+ return this.value.toString() + this.units;
676
+ }
677
+ }
678
+ });
679
+
680
+ JSGlobalObject.CSSPercentageToken = function CSSPercentageToken(value){
572
681
  this.value = value;
573
- this.toString = function(){
574
- return this.value.toString() + "%";
575
- };
576
682
  };
577
683
 
578
- CSSTokenizer.NumberToken = function(value){
684
+ Object.defineProperties(CSSPercentageToken.prototype, {
685
+ toString: {
686
+ enumerable: false,
687
+ value: function CSSPercentageToken_toString(){
688
+ return this.value.toString() + "%";
689
+ }
690
+ }
691
+ });
692
+
693
+ JSGlobalObject.CSSNumberToken = function CSSNumberToken(value){
579
694
  this.value = value;
580
- this.toString = function(){
581
- return this.value.toString();
582
- };
583
695
  };
584
696
 
585
- CSSTokenizer.CDCToken = function(){
586
- this.toString = function(){
587
- return "-->";
588
- };
697
+ Object.defineProperties(CSSNumberToken.prototype, {
698
+ toString: {
699
+ enumerable: false,
700
+ value: function CSSNumberToken_toString(){
701
+ return this.value.toString();
702
+ }
703
+ }
704
+ });
705
+
706
+ JSGlobalObject.CSSCDCToken = function CSSCDCToken(){
589
707
  };
590
708
 
591
- CSSTokenizer.CDOToken = function(){
592
- this.toString = function(){
593
- return "<!--";
594
- };
709
+ Object.defineProperties(CSSCDCToken.prototype, {
710
+ toString: {
711
+ enumerable: false,
712
+ value: function CSSCDCToken_toString(){
713
+ return "-->";
714
+ }
715
+ }
716
+ });
717
+
718
+ JSGlobalObject.CSSCDOToken = function CSSCDOToken(){
595
719
  };
596
720
 
597
- CSSTokenizer.OpenSquareToken = function(){
598
- this.toString = function(){
599
- return "[";
600
- };
721
+ Object.defineProperties(CSSCDOToken.prototype, {
722
+ toString: {
723
+ enumerable: false,
724
+ value: function CSSCDOToken_toString(){
725
+ return "<!--";
726
+ }
727
+ }
728
+ });
729
+
730
+ JSGlobalObject.CSSOpenSquareToken = function CSSOpenSquareToken(){
601
731
  };
602
732
 
603
- CSSTokenizer.CloseSquareToken = function(){
604
- this.toString = function(){
605
- return "]";
606
- };
733
+ Object.defineProperties(CSSOpenSquareToken.prototype, {
734
+ toString: {
735
+ enumerable: false,
736
+ value: function CSSOpenSquareToken_toString(){
737
+ return "[";
738
+ }
739
+ }
740
+ });
741
+
742
+ JSGlobalObject.CSSCloseSquareToken = function CSSCloseSquareToken(){
607
743
  };
608
744
 
609
- CSSTokenizer.OpenCurlyToken = function(){
610
- this.toString = function(){
611
- return "{";
612
- };
745
+ Object.defineProperties(CSSCloseSquareToken.prototype, {
746
+ toString: {
747
+ enumerable: false,
748
+ value: function CSSCloseSquareToken_toString(){
749
+ return "]";
750
+ }
751
+ }
752
+ });
753
+
754
+ JSGlobalObject.CSSOpenCurlyToken = function CSSOpenCurlyToken(){
613
755
  };
614
756
 
615
- CSSTokenizer.CloseCurlyToken = function(){
616
- this.toString = function(){
617
- return "}";
618
- };
757
+ Object.defineProperties(CSSOpenCurlyToken.prototype, {
758
+ toString: {
759
+ enumerable: false,
760
+ value: function CSSOpenCurlyToken_toString(){
761
+ return "{";
762
+ }
763
+ }
764
+ });
765
+
766
+ JSGlobalObject.CSSCloseCurlyToken = function CSSCloseCurlyToken(){
619
767
  };
620
768
 
621
- CSSTokenizer.DelimToken = function(char){
769
+ Object.defineProperties(CSSCloseCurlyToken.prototype, {
770
+ toString: {
771
+ enumerable: false,
772
+ value: function CSSCloseCurlyToken_toString(){
773
+ return "}";
774
+ }
775
+ }
776
+ });
777
+
778
+ JSGlobalObject.CSSDelimToken = function CSSDelimToken(char){
622
779
  this.char = char;
623
- this.toString = function(){
624
- return this.char;
625
- };
626
780
  };
627
781
 
782
+ Object.defineProperties(CSSDelimToken.prototype, {
783
+ toString: {
784
+ enumerable: false,
785
+ value: function CSSDelimToken_toString(){
786
+ return this.char;
787
+ }
788
+ }
789
+ });
790
+
628
791
  })();