Skip to content

Commit cac9f73

Browse files
committed
refactor to avoid global variable in browser
1 parent 737a7ad commit cac9f73

File tree

2 files changed

+147
-83
lines changed

2 files changed

+147
-83
lines changed

lib/CSSValue.js

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,25 +17,25 @@ CSSOM.CSSValue.prototype = {
1717

1818
// @see: http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSValue
1919
set cssText() {
20-
var c = getConstructorName(this);
20+
var name = this._getConstructorName();
2121

2222
throw new Exception('DOMException: property "cssText" of "' + name + '" is readonly!');
2323
},
2424

2525
get cssText() {
26-
var name = getConstructorName(this);
26+
var name = this._getConstructorName();
2727

2828
throw new Exception('getter "cssText" of "' + name + '" is not implemented!');
29-
}
30-
};
29+
},
3130

32-
function getConstructorName(instance) {
33-
var s = instance.constructor.toString(),
34-
c = s.match(/function\s([^\(]+)/),
35-
name = c[1];
31+
_getConstructorName: function() {
32+
var s = this.constructor.toString(),
33+
c = s.match(/function\s([^\(]+)/),
34+
name = c[1];
3635

37-
return name;
38-
}
36+
return name;
37+
}
38+
};
3939

4040

4141
//.CommonJS

lib/CSSValueExpression.js

Lines changed: 137 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,9 @@ CSSOM.CSSValueExpression.prototype.parse = function() {
3838
idx = this._idx;
3939

4040
var character = '',
41-
STATES = {
42-
LITERAL: 0,
43-
STRING: 1,
44-
REGEXP: 2
45-
},
46-
state = STATES.LITERAL,
47-
string_sep = '',
4841
expression = '',
4942
error = '',
43+
info,
5044
paren = [];
5145

5246

@@ -61,66 +55,40 @@ CSSOM.CSSValueExpression.prototype.parse = function() {
6155

6256
switch(character) {
6357
case '(':
64-
if (state == STATES.LITERAL) {
65-
paren.push(character);
66-
}
58+
paren.push(character);
6759
expression += character;
6860
break;
6961

7062
case ')':
71-
if (state == STATES.LITERAL) {
72-
paren.pop(character);
73-
}
63+
paren.pop(character);
7464
expression += character;
7565
break;
7666

7767
case '/':
78-
if (state == STATES.LITERAL) {
79-
var nextChar = token.charAt(idx + 1),
80-
regExp;
81-
if (nextChar == '/' || nextChar == '*') { // comment
82-
var commentEndChar,
83-
commentEndIdx;
84-
85-
if (nextChar == '/') { // line comment
86-
commentEndChar = '\n';
87-
} else if (nextChar == '*') { // block comment
88-
commentEndChar = '*/';
89-
}
90-
91-
commentEndIdx = token.indexOf(commentEndChar, idx + 1 + 1);
92-
if (commentEndIdx !== -1) {
93-
idx = commentEndIdx + commentEndChar.length - 1;
94-
} else {
95-
error = 'css expression error: unfinished comment in expression!';
96-
}
97-
} else if (regExp = parseJSRexExp(token, idx)) { // regexp?
98-
idx = regExp.idx;
99-
expression += regExp.regExp;
68+
if (info = this._parseJSComment(token, idx)) { // comment?
69+
if (info.error) {
70+
error = 'css expression error: unfinished comment in expression!';
10071
} else {
101-
expression += character;
72+
idx = info.idx;
73+
// ignore the comment
10274
}
103-
} else {
75+
} else if (info = this._parseJSRexExp(token, idx)) { // regexp
76+
idx = info.idx;
77+
expression += info.text;
78+
} else { // other
10479
expression += character;
10580
}
10681
break;
10782

108-
// TODO: string_sep in regexp
10983
case "'":
11084
case '"':
111-
if (state == STATES.LITERAL) {
112-
state = STATES.STRING;
113-
string_sep = character;
114-
} else if (state == STATES.STRING) {
115-
if (string_sep == character) {
116-
var matched = expression.match(/\\+$/);
117-
if (!matched || matched[0].length % 2 == 0) {
118-
state = STATES.LITERAL;
119-
string_sep = '';
120-
}
121-
}
85+
info = this._parseJSString(token, idx, character);
86+
if (info) { // string
87+
idx = info.idx;
88+
expression += info.text;
89+
} else {
90+
expression += character;
12291
}
123-
expression += character;
12492
break;
12593

12694
default:
@@ -154,6 +122,79 @@ CSSOM.CSSValueExpression.prototype.parse = function() {
154122
};
155123

156124

125+
/**
126+
*
127+
* @return {Object|false}
128+
* - idx:
129+
* - text:
130+
* or
131+
* - error:
132+
* or
133+
* false
134+
*
135+
*/
136+
CSSOM.CSSValueExpression.prototype._parseJSComment = function(token, idx) {
137+
var nextChar = token.charAt(idx + 1),
138+
text;
139+
140+
if (nextChar == '/' || nextChar == '*') {
141+
var startIdx = idx,
142+
endIdx,
143+
commentEndChar;
144+
145+
if (nextChar == '/') { // line comment
146+
commentEndChar = '\n';
147+
} else if (nextChar == '*') { // block comment
148+
commentEndChar = '*/';
149+
}
150+
151+
endIdx = token.indexOf(commentEndChar, startIdx + 1 + 1);
152+
if (endIdx !== -1) {
153+
endIdx = endIdx + commentEndChar.length - 1;
154+
text = token.substring(idx, endIdx + 1);
155+
return {
156+
idx: endIdx,
157+
text: text
158+
}
159+
} else {
160+
error = 'css expression error: unfinished comment in expression!';
161+
return {
162+
error: error
163+
}
164+
}
165+
} else {
166+
return false;
167+
}
168+
};
169+
170+
171+
/**
172+
*
173+
* @return {Object|false}
174+
* - idx:
175+
* - text:
176+
* or
177+
* false
178+
*
179+
*/
180+
CSSOM.CSSValueExpression.prototype._parseJSString = function(token, idx, sep) {
181+
var endIdx = this._findMatchedIdx(token, idx, sep),
182+
text;
183+
184+
if (endIdx === -1) {
185+
return false;
186+
} else {
187+
endIdx = endIdx + sep.length;
188+
text = token.substring(idx, endIdx);
189+
190+
return {
191+
idx: endIdx,
192+
text: text
193+
}
194+
}
195+
};
196+
197+
157198
/**
158199
* parse regexp in css expression
159200
*
@@ -212,7 +253,7 @@ instanceof /a/
212253
void /a/
213254
214255
*/
215-
function parseJSRexExp(token, idx) {
256+
CSSOM.CSSValueExpression.prototype._parseJSRexExp = function(token, idx) {
216257
var before = token.substring(0, idx).trimRight(),
217258
legalRegx = [
218259
/^$/,
@@ -248,39 +289,62 @@ function parseJSRexExp(token, idx) {
248289
if (!isLegal) {
249290
return false;
250291
} else {
251-
var startIdx = idx,
252-
regexp;
292+
var sep = '/',
293+
endIdx = this._findMatchedIdx(token, idx, sep),
294+
text;
295+
if (endIdx === -1) {
296+
return false;
297+
} else {
298+
endIdx = endIdx + sep.length;
299+
text = token.substring(idx, endIdx);
300+
301+
return {
302+
idx: endIdx,
303+
text: text
304+
}
305+
}
306+
}
307+
};
308+
309+
310+
/**
311+
*
312+
* find next sep(same line) index in `token`
313+
*
314+
* @return {Number}
315+
*
316+
*/
317+
CSSOM.CSSValueExpression.prototype._findMatchedIdx = function(token, idx, sep) {
318+
var startIdx = idx,
319+
endIdx;
320+
321+
var NOT_FOUND = -1;
253322

254-
while(true) {
255-
var regEndIdx = token.indexOf('/', startIdx + 1);
323+
while(true) {
324+
endIdx = token.indexOf(sep, startIdx + 1);
256325

257-
if (regEndIdx === -1) {
258-
return false;
326+
if (endIdx === -1) { // not found
327+
endIdx = NOT_FOUND;
328+
break;
329+
} else {
330+
var text = token.substring(idx + 1, endIdx),
331+
matched = text.match(/\\+$/);
332+
if (!matched || matched[0] % 2 == 0) { // not escaped
333+
break;
259334
} else {
260-
regexp = token.substring(idx + 1, regEndIdx);
261-
var matched = regexp.match(/\\+$/);
262-
if (!matched || matched[0] % 2 == 0) {
263-
regexp = '/' + regexp + '/';
264-
break;
265-
} else {
266-
startIdx = regEndIdx;
267-
}
335+
startIdx = endIdx;
268336
}
269337
}
270338
}
271339

272-
// validate
273-
// RegExp boundary(/) must be in the same line
340+
// boundary must be in the same line(js sting or regexp)
274341
var nextNewLineIdx = token.indexOf('\n', idx + 1);
275-
if (nextNewLineIdx < regEndIdx) {
276-
return false;
342+
if (nextNewLineIdx < endIdx) {
343+
endIdx = NOT_FOUND;
277344
}
278345

279346

280-
return {
281-
idx: regEndIdx,
282-
regExp: regexp
283-
};
347+
return endIdx;
284348
}
285349

286350

0 commit comments

Comments
 (0)