@@ -6,15 +6,16 @@ var fs = require("fs");
6
6
var acorn = require ( "acorn" ) ;
7
7
8
8
var file = process . argv [ 2 ] ;
9
+ var chapNum = Number ( file . match ( / ^ \d * / ) [ 0 ] ) ;
9
10
var input = fs . readFileSync ( file , "utf8" ) ;
10
11
11
- var code = "var alert = function() {}, prompt = function() { return 'x'; }, confirm = function() { return true; }; window = this;\n" ;
12
+ var baseCode = "var alert = function() {}, prompt = function() { return 'x'; }, confirm = function() { return true; }; window = this; requestAnimationFrame = setTimeout = clearTimeout = setInterval = clearInterval = Math.min ;\n" ;
12
13
13
14
var include = / \n : l o a d _ f i l e s : ( \[ [ ^ \] ] + \] ) / . exec ( input ) ;
14
15
if ( include ) JSON . parse ( include [ 1 ] ) . forEach ( function ( fileName ) {
15
16
var text = fs . readFileSync ( "html/" + fileName ) ;
16
17
if ( ! / \/ \/ t e s t : n o / . test ( text ) )
17
- code += text ;
18
+ baseCode += text ;
18
19
} ) ;
19
20
20
21
function wrapTestOutput ( snippet , config ) {
@@ -36,12 +37,27 @@ function pos(index) {
36
37
return "line " + ( input . slice ( 0 , index ) . split ( "\n" ) . length + 1 ) ;
37
38
}
38
39
39
- var re = / ( (?: \/ \/ .* \n | \s ) * ) (?: [ s a n d b o x = . * \n ) ? \[ s o u r c e , j a v a s c r i p t \] \n - - - - \n ( [ \s \S ] * ?\n ) - - - - / g, m ;
40
+ var sandboxes = { } , anonId = 0 ;
41
+
42
+ var re = / ( (?: \/ \/ .* \n | \s ) * ) (?: \[ s a n d b o x = " ( [ ^ " ] * ) " \] \n ) ? \[ s o u r c e , ( [ ^ \] ] + ) \] \n - - - - \n ( [ \s \S ] * ?\n ) - - - - / g, m ;
40
43
while ( m = re . exec ( input ) ) {
41
- var snippet = m [ 2 ] , hasConf = m [ 1 ] . match ( / \/ \/ t e s t : ( .* ) / ) , config = hasConf ? hasConf [ 1 ] : "" ;
44
+ var snippet = m [ 4 ] , hasConf = m [ 1 ] . match ( / \/ \/ t e s t : ( .* ) / ) ;
45
+ var sandbox = m [ 2 ] || "null" , type = m [ 3 ] , config = hasConf ? hasConf [ 1 ] : "" ;
42
46
var where = pos ( m . index ) ;
47
+
48
+ if ( type != "javascript" && type != "text/html" ) continue ;
49
+
50
+ var boxId = m [ 2 ] || ( type == "javascript" ? "null" : "box" + ( ++ anonId ) ) ;
51
+ var sandbox = sandboxes [ boxId ] ;
52
+ if ( ! sandbox )
53
+ sandbox = sandboxes [ boxId ] = { code : "" } ;
54
+
55
+ if ( type == "text/html" ) {
56
+ var stripped = stripHTML ( snippet ) ;
57
+ snippet = stripped . javascript ;
58
+ }
43
59
try {
44
- acorn . parse ( snippet , { strictSemicolons : ! / 0 1 _ v a l u e / . test ( file ) } ) ;
60
+ acorn . parse ( snippet , { strictSemicolons : chapNum != 1 } ) ;
45
61
} catch ( e ) {
46
62
console . log ( "parse error at " + where + ": " + e . toString ( ) ) ;
47
63
}
@@ -50,8 +66,28 @@ while (m = re.exec(input)) {
50
66
else if ( / \/ \/ → / . test ( snippet ) ) snippet = wrapTestOutput ( snippet , config ) ;
51
67
if ( / \b w r a p \b / . test ( config ) ) snippet = "(function(){\n" + snippet + "}());\n" ;
52
68
53
- code += "console.pos = " + JSON . stringify ( where ) + ";\n" ;
54
- code += snippet ;
69
+ if ( type == "text/html" ) {
70
+ if ( sandbox . html ) console . log ( "Double HTML for box " + boxId ) ;
71
+ sandbox . html = stripped . html ;
72
+ sandbox . code = stripped . included + "console.pos = " + JSON . stringify ( where ) + ";\n" + snippet + sandbox . code ;
73
+ } else {
74
+ sandbox . code += "console.pos = " + JSON . stringify ( where ) + ";\n" ;
75
+ sandbox . code += snippet ;
76
+ }
77
+ }
78
+
79
+ function stripHTML ( code ) {
80
+ var included = "" , script = "" ;
81
+ code = code . replace ( / < s c r i p t \b [ ^ > ] * ?(?: \b s r c \s * = \s * ( ' [ ^ ' ] + ' | " [ ^ " ] + " | [ ^ \s > ] + ) [ ^ > ] * ) ? > ( [ \s \S ] * ?) < \/ s c r i p t > / , function ( m , src , content ) {
82
+ if ( src ) {
83
+ if ( / [ " ' ] / . test ( src . charAt ( 0 ) ) ) src = src . slice ( 1 , src . length - 1 ) ;
84
+ included += fs . readFileSync ( "html/" + src , "utf8" ) ;
85
+ } else {
86
+ script += content ;
87
+ }
88
+ return "" ;
89
+ } ) ;
90
+ return { html : code , included : included , javascript : script } ;
55
91
}
56
92
57
93
function represent ( val ) {
@@ -136,6 +172,7 @@ var accum = "", _console = {
136
172
var clip = string . indexOf ( "…" ) , ok = false ;
137
173
if ( / \b t r a i l i n g \b / . test ( config ) ) accum = accum . replace ( / \s + ( \n | $ ) / g, "$1" ) ;
138
174
if ( / \b t r i m \b / . test ( config ) ) { accum = accum . trim ( ) ; string = string . trim ( ) ; }
175
+ if ( / \b n o n u m b e r s \b / . test ( config ) ) { accum = accum . replace ( / \d / g, "" ) ; string = string . replace ( / \d / g, "" ) ; }
139
176
if ( / \b c l i p \b / . test ( config ) ) ok = compareClipped ( string , accum ) ;
140
177
else if ( / \b j o i n \b / . test ( config ) ) ok = compareJoined ( string , accum ) ;
141
178
else if ( clip > - 1 ) ok = string . slice ( 0 , clip ) == accum . slice ( 0 , clip ) ;
@@ -145,7 +182,6 @@ var accum = "", _console = {
145
182
} ,
146
183
missingErr : function ( ) {
147
184
console . log ( "expected error not raised at " + this . pos ) ;
148
- console . log ( code ) ;
149
185
} ,
150
186
compareErr : function ( err , string ) {
151
187
if ( err . toString ( ) != string )
@@ -154,8 +190,41 @@ var accum = "", _console = {
154
190
pos : null
155
191
} ;
156
192
157
- try {
158
- ( new Function ( "console" , code ) ) ( _console ) ;
159
- } catch ( e ) {
160
- console . log ( "error raised (" + _console . pos + "): " + e . toString ( ) ) ;
193
+ function report ( err ) {
194
+ var msg = err . toString ( ) ;
195
+ if ( / ^ \[ o b j e c t / . test ( msg ) && err . message ) msg = err . message ;
196
+ console . log ( "error raised (" + _console . pos + "): " + msg , err . stack ) ;
197
+ }
198
+
199
+ var i = 0 , boxes = Object . keys ( sandboxes ) . map ( function ( k ) { return sandboxes [ k ] ; } ) ; ;
200
+ function nextSandbox ( ) {
201
+ if ( i == boxes . length ) return ;
202
+ var sandbox = boxes [ i ] ;
203
+ i ++ ;
204
+ if ( chapNum < 12 ) { // Language-only
205
+ try {
206
+ ( new Function ( "console" , baseCode + sandbox . code ) ) ( _console ) ;
207
+ nextSandbox ( ) ;
208
+ } catch ( e ) {
209
+ report ( e ) ;
210
+ }
211
+ } else {
212
+ require ( "jsdom" ) . env ( {
213
+ url : file + "/" + i ,
214
+ html : sandbox . html || "<!doctype html><body></body>" ,
215
+ src : [ baseCode ] ,
216
+ done : function ( err , window ) {
217
+ if ( err ) report ( err [ 0 ] ) ;
218
+ window . console = _console ;
219
+ window . Element . prototype . innerText = "abc" ;
220
+ try {
221
+ window . run ( sandbox . code , file + "/" + i ) ;
222
+ } catch ( e ) {
223
+ report ( e ) ;
224
+ }
225
+ nextSandbox ( ) ;
226
+ }
227
+ } ) ;
228
+ }
161
229
}
230
+ nextSandbox ( ) ;
0 commit comments