Skip to content

Commit be2ca1e

Browse files
committed
Fix build.
- Add -f flag to rm on make clean. - Use old jsmin - the new one seems to be broken.
1 parent e982349 commit be2ca1e

File tree

4 files changed

+249
-52
lines changed

4 files changed

+249
-52
lines changed

LICENSE

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ are:
99
This code is copyrighted by Marc Alexander Lehmann. Both are dually
1010
licensed under MIT and GPL2.
1111

12+
- JSMin JavaScript minifier, located at tools/jsmin.py. This code is
13+
copyrighted by Douglas Crockford and Baruch Even and has an MIT license.
14+
1215
- parseUri, a URI parser, is located in lib/http.js. This is just a small
1316
snippit. It is copyrighted 2007 by Steven Levithan and released under an
1417
MIT license.

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ website-upload: doc
4444
scp doc/* linode:~/tinyclouds/node/
4545

4646
clean:
47-
@-rm doc/node.1 doc/api.xml doc/api.html
47+
@-rm -f doc/node.1 doc/api.xml doc/api.html
4848
@tools/waf-light clean
4949

5050
distclean: clean

tools/js2c.py

Lines changed: 27 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,19 @@ def ToCArray(lines):
4545
return ", ".join(result)
4646

4747

48-
def RemoveCommentsAndTrailingWhitespace(lines):
49-
lines = re.sub(r'//.*\n', '\n', lines) # end-of-line comments
50-
lines = re.sub(re.compile(r'/\*.*?\*/', re.DOTALL), '', lines) # comments.
51-
lines = re.sub(r'\s+\n+', '\n', lines) # trailing whitespace
48+
def CompressScript(lines, do_jsmin):
49+
# If we're not expecting this code to be user visible, we can run it through
50+
# a more aggressive minifier.
51+
if do_jsmin:
52+
return jsmin.jsmin(lines)
53+
54+
# Remove stuff from the source that we don't want to appear when
55+
# people print the source code using Function.prototype.toString().
56+
# Note that we could easily compress the scripts mode but don't
57+
# since we want it to remain readable.
58+
#lines = re.sub('//.*\n', '\n', lines) # end-of-line comments
59+
#lines = re.sub(re.compile(r'/\*.*?\*/', re.DOTALL), '', lines) # comments.
60+
#lines = re.sub('\s+\n+', '\n', lines) # trailing whitespace
5261
return lines
5362

5463

@@ -87,22 +96,6 @@ def ParseValue(string):
8796
return string
8897

8998

90-
EVAL_PATTERN = re.compile(r'\beval\s*\(');
91-
WITH_PATTERN = re.compile(r'\bwith\s*\(');
92-
93-
94-
def Validate(lines, file):
95-
lines = RemoveCommentsAndTrailingWhitespace(lines)
96-
# Because of simplified context setup, eval and with is not
97-
# allowed in the natives files.
98-
eval_match = EVAL_PATTERN.search(lines)
99-
if eval_match:
100-
raise ("Eval disallowed in natives: %s" % file)
101-
with_match = WITH_PATTERN.search(lines)
102-
if with_match:
103-
raise ("With statements disallowed in natives: %s" % file)
104-
105-
10699
def ExpandConstants(lines, constants):
107100
for key, value in constants.items():
108101
lines = lines.replace(key, str(value))
@@ -162,9 +155,9 @@ def expand(self, mapping):
162155
args.append(mapping[arg])
163156
return str(self.fun(*args))
164157

165-
CONST_PATTERN = re.compile(r'^const\s+([a-zA-Z0-9_]+)\s*=\s*([^;]*);$')
166-
MACRO_PATTERN = re.compile(r'^macro\s+([a-zA-Z0-9_]+)\s*\(([^)]*)\)\s*=\s*([^;]*);$')
167-
PYTHON_MACRO_PATTERN = re.compile(r'^python\s+macro\s+([a-zA-Z0-9_]+)\s*\(([^)]*)\)\s*=\s*([^;]*);$')
158+
CONST_PATTERN = re.compile('^const\s+([a-zA-Z0-9_]+)\s*=\s*([^;]*);$')
159+
MACRO_PATTERN = re.compile('^macro\s+([a-zA-Z0-9_]+)\s*\(([^)]*)\)\s*=\s*([^;]*);$')
160+
PYTHON_MACRO_PATTERN = re.compile('^python\s+macro\s+([a-zA-Z0-9_]+)\s*\(([^)]*)\)\s*=\s*([^;]*);$')
168161

169162
def ReadMacros(lines):
170163
constants = { }
@@ -212,7 +205,7 @@ def ReadMacros(lines):
212205

213206

214207
SOURCE_DECLARATION = """\
215-
static const char %(id)s[] = { %(data)s };
208+
static const char native_%(id)s[] = { %(data)s };
216209
"""
217210

218211

@@ -230,7 +223,7 @@ def ReadMacros(lines):
230223
if (index == %(i)i) return Vector<const char>("%(name)s", %(length)i);
231224
"""
232225

233-
def JS2C(source, target, env):
226+
def JS2C(source, target):
234227
ids = []
235228
delay_ids = []
236229
modules = []
@@ -245,28 +238,24 @@ def JS2C(source, target, env):
245238

246239
# Build source code lines
247240
source_lines = [ ]
248-
249-
minifier = jsmin.JavaScriptMinifier()
250-
251241
source_lines_empty = []
252-
for module in modules:
253-
filename = str(module)
254-
delay = filename.endswith('-delay.js')
255-
lines = ReadFile(filename)
242+
for s in modules:
243+
delay = str(s).endswith('-delay.js')
244+
lines = ReadFile(str(s))
245+
do_jsmin = lines.find('// jsminify this file, js2c: jsmin') != -1
256246
lines = ExpandConstants(lines, consts)
257247
lines = ExpandMacros(lines, macros)
258-
Validate(lines, filename)
259-
lines = minifier.JSMinify(lines)
248+
lines = CompressScript(lines, do_jsmin)
260249
data = ToCArray(lines)
261-
id = (os.path.split(filename)[1])[:-3]
250+
id = (os.path.split(str(s))[1])[:-3]
262251
if delay: id = id[:-6]
263252
if delay:
264253
delay_ids.append((id, len(lines)))
265254
else:
266255
ids.append((id, len(lines)))
267256
source_lines.append(SOURCE_DECLARATION % { 'id': id, 'data': data })
268257
source_lines_empty.append(SOURCE_DECLARATION % { 'id': id, 'data': 0 })
269-
258+
270259
# Build delay support functions
271260
get_index_cases = [ ]
272261
get_script_source_cases = [ ]
@@ -311,8 +300,7 @@ def JS2C(source, target, env):
311300
'source_lines': "\n".join(source_lines),
312301
'get_index_cases': "".join(get_index_cases),
313302
'get_script_source_cases': "".join(get_script_source_cases),
314-
'get_script_name_cases': "".join(get_script_name_cases),
315-
'type': env['TYPE']
303+
'get_script_name_cases': "".join(get_script_name_cases)
316304
})
317305
output.close()
318306

@@ -324,17 +312,6 @@ def JS2C(source, target, env):
324312
'source_lines': "\n".join(source_lines_empty),
325313
'get_index_cases': "".join(get_index_cases),
326314
'get_script_source_cases': "".join(get_script_source_cases),
327-
'get_script_name_cases': "".join(get_script_name_cases),
328-
'type': env['TYPE']
315+
'get_script_name_cases': "".join(get_script_name_cases)
329316
})
330317
output.close()
331-
332-
def main():
333-
natives = sys.argv[1]
334-
natives_empty = sys.argv[2]
335-
type = sys.argv[3]
336-
source_files = sys.argv[4:]
337-
JS2C(source_files, [natives, natives_empty], { 'TYPE': type })
338-
339-
if __name__ == "__main__":
340-
main()

tools/jsmin.py

Lines changed: 0 additions & 1 deletion
This file was deleted.

tools/jsmin.py

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
#!/usr/bin/python
2+
3+
# This code is original from jsmin by Douglas Crockford, it was translated to
4+
# Python by Baruch Even. The original code had the following copyright and
5+
# license.
6+
#
7+
# /* jsmin.c
8+
# 2007-05-22
9+
#
10+
# Copyright (c) 2002 Douglas Crockford (www.crockford.com)
11+
#
12+
# Permission is hereby granted, free of charge, to any person obtaining a copy of
13+
# this software and associated documentation files (the "Software"), to deal in
14+
# the Software without restriction, including without limitation the rights to
15+
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
16+
# of the Software, and to permit persons to whom the Software is furnished to do
17+
# so, subject to the following conditions:
18+
#
19+
# The above copyright notice and this permission notice shall be included in all
20+
# copies or substantial portions of the Software.
21+
#
22+
# The Software shall be used for Good, not Evil.
23+
#
24+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30+
# SOFTWARE.
31+
# */
32+
33+
from StringIO import StringIO
34+
35+
def jsmin(js):
36+
ins = StringIO(js)
37+
outs = StringIO()
38+
JavascriptMinify().minify(ins, outs)
39+
str = outs.getvalue()
40+
if len(str) > 0 and str[0] == '\n':
41+
str = str[1:]
42+
return str
43+
44+
def isAlphanum(c):
45+
"""return true if the character is a letter, digit, underscore,
46+
dollar sign, or non-ASCII character.
47+
"""
48+
return ((c >= 'a' and c <= 'z') or (c >= '0' and c <= '9') or
49+
(c >= 'A' and c <= 'Z') or c == '_' or c == '$' or c == '\\' or (c is not None and ord(c) > 126));
50+
51+
class UnterminatedComment(Exception):
52+
pass
53+
54+
class UnterminatedStringLiteral(Exception):
55+
pass
56+
57+
class UnterminatedRegularExpression(Exception):
58+
pass
59+
60+
class JavascriptMinify(object):
61+
62+
def _outA(self):
63+
self.outstream.write(self.theA)
64+
def _outB(self):
65+
self.outstream.write(self.theB)
66+
67+
def _get(self):
68+
"""return the next character from stdin. Watch out for lookahead. If
69+
the character is a control character, translate it to a space or
70+
linefeed.
71+
"""
72+
c = self.theLookahead
73+
self.theLookahead = None
74+
if c == None:
75+
c = self.instream.read(1)
76+
if c >= ' ' or c == '\n':
77+
return c
78+
if c == '': # EOF
79+
return '\000'
80+
if c == '\r':
81+
return '\n'
82+
return ' '
83+
84+
def _peek(self):
85+
self.theLookahead = self._get()
86+
return self.theLookahead
87+
88+
def _next(self):
89+
"""get the next character, excluding comments. peek() is used to see
90+
if an unescaped '/' is followed by a '/' or '*'.
91+
"""
92+
c = self._get()
93+
if c == '/' and self.theA != '\\':
94+
p = self._peek()
95+
if p == '/':
96+
c = self._get()
97+
while c > '\n':
98+
c = self._get()
99+
return c
100+
if p == '*':
101+
c = self._get()
102+
while 1:
103+
c = self._get()
104+
if c == '*':
105+
if self._peek() == '/':
106+
self._get()
107+
return ' '
108+
if c == '\000':
109+
raise UnterminatedComment()
110+
111+
return c
112+
113+
def _action(self, action):
114+
"""do something! What you do is determined by the argument:
115+
1 Output A. Copy B to A. Get the next B.
116+
2 Copy B to A. Get the next B. (Delete A).
117+
3 Get the next B. (Delete B).
118+
action treats a string as a single character. Wow!
119+
action recognizes a regular expression if it is preceded by ( or , or =.
120+
"""
121+
if action <= 1:
122+
self._outA()
123+
124+
if action <= 2:
125+
self.theA = self.theB
126+
if self.theA == "'" or self.theA == '"':
127+
while 1:
128+
self._outA()
129+
self.theA = self._get()
130+
if self.theA == self.theB:
131+
break
132+
if self.theA <= '\n':
133+
raise UnterminatedStringLiteral()
134+
if self.theA == '\\':
135+
self._outA()
136+
self.theA = self._get()
137+
138+
139+
if action <= 3:
140+
self.theB = self._next()
141+
if self.theB == '/' and (self.theA == '(' or self.theA == ',' or
142+
self.theA == '=' or self.theA == ':' or
143+
self.theA == '[' or self.theA == '?' or
144+
self.theA == '!' or self.theA == '&' or
145+
self.theA == '|' or self.theA == ';' or
146+
self.theA == '{' or self.theA == '}' or
147+
self.theA == '\n'):
148+
self._outA()
149+
self._outB()
150+
while 1:
151+
self.theA = self._get()
152+
if self.theA == '/':
153+
break
154+
elif self.theA == '\\':
155+
self._outA()
156+
self.theA = self._get()
157+
elif self.theA <= '\n':
158+
raise UnterminatedRegularExpression()
159+
self._outA()
160+
self.theB = self._next()
161+
162+
163+
def _jsmin(self):
164+
"""Copy the input to the output, deleting the characters which are
165+
insignificant to JavaScript. Comments will be removed. Tabs will be
166+
replaced with spaces. Carriage returns will be replaced with linefeeds.
167+
Most spaces and linefeeds will be removed.
168+
"""
169+
self.theA = '\n'
170+
self._action(3)
171+
172+
while self.theA != '\000':
173+
if self.theA == ' ':
174+
if isAlphanum(self.theB):
175+
self._action(1)
176+
else:
177+
self._action(2)
178+
elif self.theA == '\n':
179+
if self.theB in ['{', '[', '(', '+', '-']:
180+
self._action(1)
181+
elif self.theB == ' ':
182+
self._action(3)
183+
else:
184+
if isAlphanum(self.theB):
185+
self._action(1)
186+
else:
187+
self._action(2)
188+
else:
189+
if self.theB == ' ':
190+
if isAlphanum(self.theA):
191+
self._action(1)
192+
else:
193+
self._action(3)
194+
elif self.theB == '\n':
195+
if self.theA in ['}', ']', ')', '+', '-', '"', '\'']:
196+
self._action(1)
197+
else:
198+
if isAlphanum(self.theA):
199+
self._action(1)
200+
else:
201+
self._action(3)
202+
else:
203+
self._action(1)
204+
205+
def minify(self, instream, outstream):
206+
self.instream = instream
207+
self.outstream = outstream
208+
self.theA = '\n'
209+
self.theB = None
210+
self.theLookahead = None
211+
212+
self._jsmin()
213+
self.instream.close()
214+
215+
if __name__ == '__main__':
216+
import sys
217+
jsm = JavascriptMinify()
218+
jsm.minify(sys.stdin, sys.stdout)

0 commit comments

Comments
 (0)