mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 21:40:07 +00:00
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:
parent
9236cc458b
commit
b4be3ca2fe
|
@ -89,6 +89,9 @@ def main(outdir = None, *inputs):
|
||||||
|
|
||||||
seen.add(lib)
|
seen.add(lib)
|
||||||
|
|
||||||
|
if lib.startswith('dart:'):
|
||||||
|
continue
|
||||||
|
|
||||||
if (dirname(dirname(lib)).endswith('dom/generated/src')
|
if (dirname(dirname(lib)).endswith('dom/generated/src')
|
||||||
or dirname(lib).endswith('dom/src')):
|
or dirname(lib).endswith('dom/src')):
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -24,12 +24,29 @@ sys.path.append(TOOLS_PATH)
|
||||||
import utils
|
import utils
|
||||||
|
|
||||||
DART_MIME_TYPE = "application/dart"
|
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:dom');
|
||||||
#import('dart:json');
|
#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>'
|
CSS_TEMPLATE = '<style type="text/css">%s</style>'
|
||||||
CHROMIUM_SCRIPT_TEMPLATE = '<script type="application/javascript">%s</script>'
|
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")
|
"The script body should be empty if src is specified")
|
||||||
elif src.endswith('.dart'):
|
elif src.endswith('.dart'):
|
||||||
indir = tempfile.mkdtemp()
|
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:
|
else:
|
||||||
raise ConverterException("invalid file type:" + src)
|
raise ConverterException("invalid file type:" + src)
|
||||||
else:
|
else:
|
||||||
|
@ -86,18 +121,23 @@ class DartCompiler(object):
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
indir = tempfile.mkdtemp()
|
indir = tempfile.mkdtemp()
|
||||||
|
|
||||||
inputfile = join(indir, 'code.dart')
|
inputfile = join(indir, 'code.dart')
|
||||||
with open(inputfile, 'w') as f:
|
with open(inputfile, 'w') as f:
|
||||||
f.write(DARTC_INPUT_IMPORTS)
|
f.write(DARTC_INLINE_CODE_ADDITIONAL_IMPORTS)
|
||||||
f.write(body)
|
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)
|
self.verbose)
|
||||||
if status:
|
if status:
|
||||||
raise ConverterException()
|
raise ConverterException()
|
||||||
|
|
||||||
# Inline the compiled code in the page
|
# 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()
|
res = f.read()
|
||||||
|
|
||||||
# Cleanup
|
# Cleanup
|
||||||
|
@ -107,9 +147,9 @@ class DartCompiler(object):
|
||||||
return CHROMIUM_SCRIPT_TEMPLATE % res
|
return CHROMIUM_SCRIPT_TEMPLATE % res
|
||||||
|
|
||||||
def compileCommand(self, inputfile, outdir):
|
def compileCommand(self, inputfile, outdir):
|
||||||
cmd = [abspath(join(CLIENT_PATH,
|
cmd = [abspath(join(DART_PATH,
|
||||||
# TODO(sigmund): support also mode = release
|
# TODO(sigmund): support also mode = release
|
||||||
utils.GetBuildRoot(utils.GuessOS(), 'debug', 'dartc'),
|
utils.GetBuildRoot(utils.GuessOS(), 'debug', 'ia32'),
|
||||||
'dartc')), '-noincremental', '-out', outdir]
|
'dartc')), '-noincremental', '-out', outdir]
|
||||||
if self.optimize:
|
if self.optimize:
|
||||||
cmd.append('-optimize')
|
cmd.append('-optimize')
|
||||||
|
@ -125,14 +165,20 @@ class DartCompiler(object):
|
||||||
def execute(cmd, verbose=False):
|
def execute(cmd, verbose=False):
|
||||||
"""Execute a command in a subprocess. """
|
"""Execute a command in a subprocess. """
|
||||||
if verbose: print 'Executing: ' + ' '.join(cmd)
|
if verbose: print 'Executing: ' + ' '.join(cmd)
|
||||||
pipe = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
try:
|
||||||
output, err = pipe.communicate()
|
pipe = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
if pipe.returncode != 0:
|
output, err = pipe.communicate()
|
||||||
print 'Execution failed: ' + output + '\n' + err
|
if pipe.returncode != 0:
|
||||||
if verbose or pipe.returncode != 0:
|
print 'Execution failed: ' + output + '\n' + err
|
||||||
print output
|
if verbose or pipe.returncode != 0:
|
||||||
print err
|
print output
|
||||||
return pipe.returncode, output, err
|
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):
|
def convertPath(project_path, prefix_path):
|
||||||
""" Convert a project path (whose root corresponds to the current working
|
""" Convert a project path (whose root corresponds to the current working
|
||||||
|
@ -311,6 +357,7 @@ class DartToDartHTMLConverter(DartHTMLConverter):
|
||||||
self.outdir,
|
self.outdir,
|
||||||
convertPath(attrDic['src'], self.prefix_path)],
|
convertPath(attrDic['src'], self.prefix_path)],
|
||||||
self.verbose)
|
self.verbose)
|
||||||
|
|
||||||
if status:
|
if status:
|
||||||
raise ConverterException('calling copy_dart.py')
|
raise ConverterException('calling copy_dart.py')
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,7 @@ TEST2_HTML = """
|
||||||
"""
|
"""
|
||||||
|
|
||||||
TEST2_DART = """
|
TEST2_DART = """
|
||||||
|
#library('test2');
|
||||||
#import('dart:dom');
|
#import('dart:dom');
|
||||||
main() {
|
main() {
|
||||||
window.alert('test2!');
|
window.alert('test2!');
|
||||||
|
@ -132,12 +133,11 @@ TEST4_HTML = """
|
||||||
|
|
||||||
TEST4_DART = """
|
TEST4_DART = """
|
||||||
#import('dart:dom');
|
#import('dart:dom');
|
||||||
#import('dart:json');
|
|
||||||
#import('observable/observable.dart');
|
#import('observable/observable.dart');
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
// use imported code
|
// use imported code
|
||||||
var arr = new ObservableArray();
|
var arr = new ObservableList();
|
||||||
arr.addChangeListener((EventSummary events) {
|
arr.addChangeListener((EventSummary events) {
|
||||||
var t = ['update', 'add ',
|
var t = ['update', 'add ',
|
||||||
'remove', 'global'][events.events[0].type];
|
'remove', 'global'][events.events[0].type];
|
||||||
|
@ -171,6 +171,40 @@ Content-Type: text/plain
|
||||||
#EOF
|
#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 = {
|
FILES = {
|
||||||
'test_1.html': TEST1_HTML,
|
'test_1.html': TEST1_HTML,
|
||||||
|
|
||||||
|
@ -184,11 +218,23 @@ FILES = {
|
||||||
|
|
||||||
'test_4.html': TEST4_HTML,
|
'test_4.html': TEST4_HTML,
|
||||||
'test_4.dart': TEST4_DART,
|
'test_4.dart': TEST4_DART,
|
||||||
|
|
||||||
|
'test_5.html': TEST5_HTML,
|
||||||
}
|
}
|
||||||
|
|
||||||
INPUTS = ['test_1.html', 'test_2.html', 'test_3.html', 'test_4.html']
|
INPUTS = [
|
||||||
OUTPUTS = [TEST1_OUTPUT, TEST2_OUTPUT, TEST3_OUTPUT, TEST4_OUTPUT]
|
'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__)))
|
CLIENT_PATH = dirname(dirname(abspath(__file__)))
|
||||||
RED_COLOR = "\033[31m"
|
RED_COLOR = "\033[31m"
|
||||||
|
@ -252,7 +298,7 @@ def deleteInputFiles():
|
||||||
for filename in FILES:
|
for filename in FILES:
|
||||||
os.remove(filename)
|
os.remove(filename)
|
||||||
|
|
||||||
def runTest(test, target, verbose):
|
def runTest(test, target, verbose, keep_temporary_files):
|
||||||
inputfile = INPUTS[test]
|
inputfile = INPUTS[test]
|
||||||
suffix = '-js.html' if target == 'chromium' else '-dartium.html'
|
suffix = '-js.html' if target == 'chromium' else '-dartium.html'
|
||||||
outfile = abspath(join('out', inputfile.replace(".html", suffix)))
|
outfile = abspath(join('out', inputfile.replace(".html", suffix)))
|
||||||
|
@ -273,12 +319,17 @@ def runTest(test, target, verbose):
|
||||||
|
|
||||||
status = browserRun(
|
status = browserRun(
|
||||||
"... running compiled html in %s" % target, outfile, test, verbose)
|
"... running compiled html in %s" % target, outfile, test, verbose)
|
||||||
os.remove(outfile)
|
if not keep_temporary_files:
|
||||||
|
os.remove(outfile)
|
||||||
return status
|
return status
|
||||||
|
|
||||||
def Flags():
|
def Flags():
|
||||||
""" Consturcts a parser for extracting flags from the command line. """
|
""" Consturcts a parser for extracting flags from the command line. """
|
||||||
result = optparse.OptionParser()
|
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",
|
result.add_option("-v", "--verbose",
|
||||||
help="Print verbose output",
|
help="Print verbose output",
|
||||||
default=False,
|
default=False,
|
||||||
|
@ -290,23 +341,38 @@ def Flags():
|
||||||
result.set_usage("htmlconverter_test.py [--verbose -t chromium,dartium]")
|
result.set_usage("htmlconverter_test.py [--verbose -t chromium,dartium]")
|
||||||
return result
|
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():
|
def main():
|
||||||
os.chdir(CLIENT_PATH)
|
os.chdir(CLIENT_PATH)
|
||||||
parser = Flags()
|
parser = Flags()
|
||||||
options, args = parser.parse_args()
|
options, args = parser.parse_args()
|
||||||
|
verbose = options.verbose
|
||||||
|
keep_temporary_files = options.keep_temporary_files
|
||||||
|
|
||||||
createInputFiles()
|
createInputFiles()
|
||||||
for test in range(len(INPUTS)):
|
for test in range(len(INPUTS)):
|
||||||
if 'chromium' in options.target:
|
if shouldRunTest(test, args):
|
||||||
if runTest(test, 'chromium', options.verbose) != 0:
|
if 'chromium' in options.target:
|
||||||
deleteInputFiles()
|
if runTest(test, 'chromium', verbose, keep_temporary_files) != 0:
|
||||||
return 1
|
if not keep_temporary_files:
|
||||||
if 'dartium' in options.target:
|
deleteInputFiles()
|
||||||
if runTest(test, 'dartium', options.verbose) != 0:
|
return 1
|
||||||
deleteInputFiles()
|
if 'dartium' in options.target:
|
||||||
return 1
|
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
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue