Skip to content

Commit fa0cb68

Browse files
committed
Optimize tokenize()
- Wrap internal variables in a closure to prevent repeated instantiation when called. - Define every internal function using a direct function expression rather than an anonymous function.
1 parent 31a6a95 commit fa0cb68

File tree

1 file changed

+69
-58
lines changed

1 file changed

+69
-58
lines changed

parse-css.js

Lines changed: 69 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -78,45 +78,48 @@ function asciiCaselessMatch(s1, s2) {
7878
return s1.toLowerCase() == s2.toLowerCase();
7979
}
8080

81-
function tokenize(str) {
82-
str = preprocess(str);
83-
var i = -1;
84-
var tokens = [];
85-
var code;
81+
var tokenize = (function () {
82+
let str;
83+
let i;
84+
let tokens;
85+
let code;
8686

87-
var codepoint = function(i) {
87+
function codepoint(i) {
8888
if(i >= str.length) {
8989
return 0;
9090
}
9191
return str[i];
9292
}
93-
var next = function(num) {
93+
function next(num) {
9494
if(num === undefined)
9595
num = 1;
9696
if(num > 3)
9797
throw new SpecError("no more than three codepoints of lookahead.");
9898
return codepoint(i+num);
99-
};
100-
var consume = function(num) {
99+
}
100+
function consume(num) {
101101
if(num === undefined)
102102
num = 1;
103103
i += num;
104104
code = codepoint(i);
105105
//console.log('Consume '+i+' '+String.fromCharCode(code) + ' 0x' + code.toString(16));
106106
return true;
107-
};
108-
var reconsume = function() {
107+
}
108+
function reconsume() {
109109
i -= 1;
110110
return true;
111-
};
112-
var eof = function(codepoint) {
111+
}
112+
function eof(codepoint) {
113113
if(codepoint === undefined) codepoint = code;
114114
return codepoint == 0;
115-
};
116-
var donothing = function() {};
117-
var parseerror = function() { console.log("Parse error at index " + i + ", processing codepoint 0x" + code.toString(16) + ".");return true; };
115+
}
116+
function donothing() {}
117+
function parseerror() {
118+
console.log("Parse error at index " + i + ", processing codepoint 0x" + code.toString(16) + ".");
119+
return true;
120+
}
118121

119-
var consumeAToken = function() {
122+
function consumeAToken() {
120123
consumeComments();
121124
consume();
122125
if(whitespace(code)) {
@@ -206,9 +209,9 @@ function tokenize(str) {
206209
}
207210
else if(eof()) return new EOFToken();
208211
else return new DelimToken(code);
209-
};
212+
}
210213

211-
var consumeComments = function() {
214+
function consumeComments() {
212215
while(next(1) == 0x2f && next(2) == 0x2a) {
213216
consume(2);
214217
while(true) {
@@ -222,9 +225,9 @@ function tokenize(str) {
222225
}
223226
}
224227
}
225-
};
228+
}
226229

227-
var consumeANumericToken = function() {
230+
function consumeANumericToken() {
228231
var {value, isInteger, sign} = consumeANumber();
229232
if(wouldStartAnIdentifier(next(1), next(2), next(3))) {
230233
const unit = consumeAName();
@@ -235,9 +238,9 @@ function tokenize(str) {
235238
} else {
236239
return new NumberToken(value, isInteger, sign);
237240
}
238-
};
241+
}
239242

240-
var consumeAnIdentlikeToken = function() {
243+
function consumeAnIdentlikeToken() {
241244
var str = consumeAName();
242245
if(str.toLowerCase() == "url" && next() == 0x28) {
243246
consume();
@@ -255,9 +258,9 @@ function tokenize(str) {
255258
} else {
256259
return new IdentToken(str);
257260
}
258-
};
261+
}
259262

260-
var consumeAStringToken = function(endingCodePoint) {
263+
function consumeAStringToken(endingCodePoint) {
261264
if(endingCodePoint === undefined) endingCodePoint = code;
262265
var string = "";
263266
while(consume()) {
@@ -279,9 +282,9 @@ function tokenize(str) {
279282
string += String.fromCodePoint(code);
280283
}
281284
}
282-
};
285+
}
283286

284-
var consumeAURLToken = function() {
287+
function consumeAURLToken() {
285288
var token = new URLToken("");
286289
while(whitespace(next())) consume();
287290
if(eof(next())) return token;
@@ -313,9 +316,9 @@ function tokenize(str) {
313316
token.value += String.fromCodePoint(code);
314317
}
315318
}
316-
};
319+
}
317320

318-
var consumeEscape = function() {
321+
function consumeEscape() {
319322
// Assume the the current character is the \
320323
// and the next code point is not a newline.
321324
consume();
@@ -339,18 +342,18 @@ function tokenize(str) {
339342
} else {
340343
return code;
341344
}
342-
};
345+
}
343346

344-
var areAValidEscape = function(c1, c2) {
347+
function areAValidEscape(c1, c2) {
345348
if(c1 != 0x5c) return false;
346349
if(newline(c2)) return false;
347350
return true;
348-
};
349-
var startsWithAValidEscape = function() {
351+
}
352+
function startsWithAValidEscape() {
350353
return areAValidEscape(code, next());
351-
};
354+
}
352355

353-
var wouldStartAnIdentifier = function(c1, c2, c3) {
356+
function wouldStartAnIdentifier(c1, c2, c3) {
354357
if(c1 == 0x2d) {
355358
return namestartchar(c2) || c2 == 0x2d || areAValidEscape(c2, c3);
356359
} else if(namestartchar(c1)) {
@@ -360,12 +363,12 @@ function tokenize(str) {
360363
} else {
361364
return false;
362365
}
363-
};
364-
var startsWithAnIdentifier = function() {
366+
}
367+
function startsWithAnIdentifier() {
365368
return wouldStartAnIdentifier(code, next(1), next(2));
366-
};
369+
}
367370

368-
var wouldStartANumber = function(c1, c2, c3) {
371+
function wouldStartANumber(c1, c2, c3) {
369372
if(c1 == 0x2b || c1 == 0x2d) {
370373
if(digit(c2)) return true;
371374
if(c2 == 0x2e && digit(c3)) return true;
@@ -378,12 +381,12 @@ function tokenize(str) {
378381
} else {
379382
return false;
380383
}
381-
};
382-
var startsWithANumber = function() {
384+
}
385+
function startsWithANumber() {
383386
return wouldStartANumber(code, next(1), next(2));
384-
};
387+
}
385388

386-
var consumeAName = function() {
389+
function consumeAName() {
387390
var result = "";
388391
while(consume()) {
389392
if(namechar(code)) {
@@ -395,9 +398,9 @@ function tokenize(str) {
395398
return result;
396399
}
397400
}
398-
};
401+
}
399402

400-
var consumeANumber = function() {
403+
function consumeANumber() {
401404
let isInteger = true;
402405
let sign;
403406
let numberPart = "";
@@ -443,9 +446,9 @@ function tokenize(str) {
443446
// if(exponentPart) value = value * Math.pow(10, +exponentPart);
444447

445448
return {value, isInteger, sign};
446-
};
449+
}
447450

448-
var consumeTheRemnantsOfABadURL = function() {
451+
function consumeTheRemnantsOfABadURL() {
449452
while(consume()) {
450453
if(code == 0x29 || eof()) {
451454
return;
@@ -456,22 +459,30 @@ function tokenize(str) {
456459
donothing();
457460
}
458461
}
459-
};
462+
}
460463

461464

465+
function tokenize(input) {
466+
str = preprocess(input);
467+
i = -1;
468+
tokens = [];
469+
code;
462470

463-
var iterationCount = 0;
464-
while (true) {
465-
var token = consumeAToken();
466-
tokens.push(token);
467-
if (token instanceof EOFToken) {
468-
break;
471+
var iterationCount = 0;
472+
while (true) {
473+
var token = consumeAToken();
474+
tokens.push(token);
475+
if (token instanceof EOFToken) {
476+
break;
477+
}
478+
iterationCount++;
479+
if(iterationCount > str.length*2) throw new Error("I'm infinite-looping!");
469480
}
470-
iterationCount++;
471-
if(iterationCount > str.length*2) throw new Error("I'm infinite-looping!");
481+
return tokens;
472482
}
473-
return tokens;
474-
}
483+
484+
return tokenize;
485+
})();
475486

476487
class CSSParserToken {
477488
constructor(type) {

0 commit comments

Comments
 (0)