htmlconverter: support DOMContentLoaded and more:

- adds support for running code on DOMContentLoaded, but only for chromium
- fix errors in tests after rename to List
- fix test due to bug in dartium importing dart:json
- add flag to htmlconverter_test to keep temporary files (for debugging)
- adds a test that relies on DOMCOntentLoaded (this will fail in dartium)
- make htmlconverter.py use the dartc build in the top-level directory

Review URL: https://chromereviews.googleplex.com/3512025

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@69 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
sigmund@google.com 2011-10-05 20:31:50 +00:00
parent 9236cc458b
commit b4be3ca2fe
3 changed files with 146 additions and 30 deletions

View file

@ -89,6 +89,9 @@ def main(outdir = None, *inputs):
seen.add(lib)
if lib.startswith('dart:'):
continue
if (dirname(dirname(lib)).endswith('dom/generated/src')
or dirname(lib).endswith('dom/src')):
continue

View file

@ -24,12 +24,29 @@ sys.path.append(TOOLS_PATH)
import utils
DART_MIME_TYPE = "application/dart"
IMPORT_SOURCE_PATTERN = "(#import|#source)(\(['\"])([^'\"]*)(['\"]\);)"
DARTC_INPUT_IMPORTS = """
DARTC_INLINE_CODE_ADDITIONAL_IMPORTS = """
#library('inlinedcode');
#import('dart:dom');
#import('dart:json');
"""
ENTRY_POINT = """
#library('entry');
#import('dart:dom');
#import('%s', prefix: 'original');
main() {
// Ensure the code starts on DOM content loaded.
if (document.readyState == "interactive" ||
document.readyState == "complete") {
original.main();
} else {
window.addEventListener('DOMContentLoaded', (e) => original.main(), false);
}
}
"""
CSS_TEMPLATE = '<style type="text/css">%s</style>'
CHROMIUM_SCRIPT_TEMPLATE = '<script type="application/javascript">%s</script>'
@ -76,7 +93,25 @@ class DartCompiler(object):
"The script body should be empty if src is specified")
elif src.endswith('.dart'):
indir = tempfile.mkdtemp()
inputfile = src
inputfile = abspath(src)
with open(inputfile, 'r') as f:
contents = f.read();
# We will import the source file to emulate in JS that code is run after
# DOMContentLoaded. We need a #library to ensure #import won't fail:
if not '#library' in contents:
def repl(matchobj):
path = matchobj.group(3)
if path.startswith('dart:'):
return matchobj.group(0)
return (matchobj.group(1) + matchobj.group(2)
+ abspath(path) + matchobj.group(4))
contents = re.sub(IMPORT_SOURCE_PATTERN, repl, contents)
inputfile = join(indir, 'code.dart')
with open(inputfile, 'w') as f:
f.write("#library('code');")
f.write(contents)
else:
raise ConverterException("invalid file type:" + src)
else:
@ -86,18 +121,23 @@ class DartCompiler(object):
return ''
indir = tempfile.mkdtemp()
inputfile = join(indir, 'code.dart')
with open(inputfile, 'w') as f:
f.write(DARTC_INPUT_IMPORTS)
f.write(DARTC_INLINE_CODE_ADDITIONAL_IMPORTS)
f.write(body)
status, out, err = execute(self.compileCommand(inputfile, outdir),
wrappedfile = join(indir, 'entry.dart')
with open(wrappedfile, 'w') as f:
f.write(ENTRY_POINT % inputfile)
status, out, err = execute(self.compileCommand(wrappedfile, outdir),
self.verbose)
if status:
raise ConverterException()
# Inline the compiled code in the page
with open(self.outputFileName(inputfile, outdir), 'r') as f:
with open(self.outputFileName(wrappedfile, outdir), 'r') as f:
res = f.read()
# Cleanup
@ -107,9 +147,9 @@ class DartCompiler(object):
return CHROMIUM_SCRIPT_TEMPLATE % res
def compileCommand(self, inputfile, outdir):
cmd = [abspath(join(CLIENT_PATH,
cmd = [abspath(join(DART_PATH,
# TODO(sigmund): support also mode = release
utils.GetBuildRoot(utils.GuessOS(), 'debug', 'dartc'),
utils.GetBuildRoot(utils.GuessOS(), 'debug', 'ia32'),
'dartc')), '-noincremental', '-out', outdir]
if self.optimize:
cmd.append('-optimize')
@ -125,14 +165,20 @@ class DartCompiler(object):
def execute(cmd, verbose=False):
"""Execute a command in a subprocess. """
if verbose: print 'Executing: ' + ' '.join(cmd)
pipe = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output, err = pipe.communicate()
if pipe.returncode != 0:
print 'Execution failed: ' + output + '\n' + err
if verbose or pipe.returncode != 0:
print output
print err
return pipe.returncode, output, err
try:
pipe = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output, err = pipe.communicate()
if pipe.returncode != 0:
print 'Execution failed: ' + output + '\n' + err
if verbose or pipe.returncode != 0:
print output
print err
return pipe.returncode, output, err
except Exception as e:
print 'Exception when executing: ' + ' '.join(cmd)
print e
return 1, None, None
def convertPath(project_path, prefix_path):
""" Convert a project path (whose root corresponds to the current working
@ -311,6 +357,7 @@ class DartToDartHTMLConverter(DartHTMLConverter):
self.outdir,
convertPath(attrDic['src'], self.prefix_path)],
self.verbose)
if status:
raise ConverterException('calling copy_dart.py')

View file

@ -59,6 +59,7 @@ TEST2_HTML = """
"""
TEST2_DART = """
#library('test2');
#import('dart:dom');
main() {
window.alert('test2!');
@ -132,12 +133,11 @@ TEST4_HTML = """
TEST4_DART = """
#import('dart:dom');
#import('dart:json');
#import('observable/observable.dart');
main() {
// use imported code
var arr = new ObservableArray();
var arr = new ObservableList();
arr.addChangeListener((EventSummary events) {
var t = ['update', 'add ',
'remove', 'global'][events.events[0].type];
@ -171,6 +171,40 @@ Content-Type: text/plain
#EOF
"""
TEST5_HTML = """
<html>
<head></head>
<body>
<script type="application/javascript">
if (window.layoutTestController) {
window.layoutTestController.dumpAsText();
}
</script>
<!-- embed source code -->
<script type="application/dart">
main() {
var element = document.getElementById("test5div");
if (element == null) {
window.alert("this script shoulnd't be run synchronously");
} else {
window.alert(element.innerHTML);
}
}
</script>
<div id="test5div">this is visible on DOMContentLoaded</div>
</body>
</html>
"""
TEST5_OUTPUT = """
ALERT: this is visible on DOMContentLoaded
Content-Type: text/plain
this is visible on DOMContentLoaded
#EOF
"""
FILES = {
'test_1.html': TEST1_HTML,
@ -184,11 +218,23 @@ FILES = {
'test_4.html': TEST4_HTML,
'test_4.dart': TEST4_DART,
'test_5.html': TEST5_HTML,
}
INPUTS = ['test_1.html', 'test_2.html', 'test_3.html', 'test_4.html']
OUTPUTS = [TEST1_OUTPUT, TEST2_OUTPUT, TEST3_OUTPUT, TEST4_OUTPUT]
INPUTS = [
'test_1.html',
'test_2.html',
'test_3.html',
'test_4.html',
'test_5.html']
OUTPUTS = [
TEST1_OUTPUT,
TEST2_OUTPUT,
TEST3_OUTPUT,
TEST4_OUTPUT,
TEST5_OUTPUT]
CLIENT_PATH = dirname(dirname(abspath(__file__)))
RED_COLOR = "\033[31m"
@ -252,7 +298,7 @@ def deleteInputFiles():
for filename in FILES:
os.remove(filename)
def runTest(test, target, verbose):
def runTest(test, target, verbose, keep_temporary_files):
inputfile = INPUTS[test]
suffix = '-js.html' if target == 'chromium' else '-dartium.html'
outfile = abspath(join('out', inputfile.replace(".html", suffix)))
@ -273,12 +319,17 @@ def runTest(test, target, verbose):
status = browserRun(
"... running compiled html in %s" % target, outfile, test, verbose)
os.remove(outfile)
if not keep_temporary_files:
os.remove(outfile)
return status
def Flags():
""" Consturcts a parser for extracting flags from the command line. """
result = optparse.OptionParser()
result.add_option("--keep_temporary_files",
help="Keep temporary files created for each test",
default=False,
action="store_true")
result.add_option("-v", "--verbose",
help="Print verbose output",
default=False,
@ -290,23 +341,38 @@ def Flags():
result.set_usage("htmlconverter_test.py [--verbose -t chromium,dartium]")
return result
def shouldRunTest(test, prefixes):
if len(prefixes) == 0:
return True
for a in prefixes:
if INPUTS[test].startswith(a):
return True
return False
def main():
os.chdir(CLIENT_PATH)
parser = Flags()
options, args = parser.parse_args()
verbose = options.verbose
keep_temporary_files = options.keep_temporary_files
createInputFiles()
for test in range(len(INPUTS)):
if 'chromium' in options.target:
if runTest(test, 'chromium', options.verbose) != 0:
deleteInputFiles()
return 1
if 'dartium' in options.target:
if runTest(test, 'dartium', options.verbose) != 0:
deleteInputFiles()
return 1
if shouldRunTest(test, args):
if 'chromium' in options.target:
if runTest(test, 'chromium', verbose, keep_temporary_files) != 0:
if not keep_temporary_files:
deleteInputFiles()
return 1
if 'dartium' in options.target:
if runTest(test, 'dartium', verbose, keep_temporary_files) != 0:
if not keep_temporary_files:
deleteInputFiles()
return 1
deleteInputFiles()
if not keep_temporary_files:
deleteInputFiles()
return 0