diff --git a/pkg/dev_compiler/lib/runtime/_classes.js b/pkg/dev_compiler/lib/runtime/_classes.js index 4497fb7aa54e..9487e077b699 100644 --- a/pkg/dev_compiler/lib/runtime/_classes.js +++ b/pkg/dev_compiler/lib/runtime/_classes.js @@ -393,6 +393,10 @@ dart_library.library('dart_runtime/_classes', null, /* Imports */[ function canonicalMember(obj, name) { if (obj != null && obj[_extensionType]) return dartx[name]; + // Check for certain names that we can't use in JS + if (name == 'constructor' || name == 'prototype') { + name = '+' + name; + } return name; } exports.canonicalMember = canonicalMember; diff --git a/pkg/dev_compiler/lib/runtime/_types.js b/pkg/dev_compiler/lib/runtime/_types.js index 691d9f2e9739..8c8122e7e47d 100644 --- a/pkg/dev_compiler/lib/runtime/_types.js +++ b/pkg/dev_compiler/lib/runtime/_types.js @@ -16,8 +16,6 @@ dart_library.library('dart_runtime/_types', null, /* Imports */[ const getOwnPropertyNames = Object.getOwnPropertyNames; const assert = dart_utils.assert; - const copyProperties = dart_utils.copyProperties; - const safeGetOwnProperty = dart_utils.safeGetOwnProperty; /** * Types in dart are represented at runtime as follows. @@ -64,13 +62,13 @@ dart_library.library('dart_runtime/_types', null, /* Imports */[ class Bottom extends TypeRep { toString() { return "bottom"; } - }; + } let bottomR = new Bottom(); exports.bottom = bottomR; class JSObject extends TypeRep { toString() { return "NativeJavaScriptObject"; } - }; + } let jsobjectR = new JSObject(); exports.jsobject = jsobjectR; diff --git a/pkg/dev_compiler/lib/src/codegen/js_codegen.dart b/pkg/dev_compiler/lib/src/codegen/js_codegen.dart index 048bb5c8508f..b1877e9a41d4 100644 --- a/pkg/dev_compiler/lib/src/codegen/js_codegen.dart +++ b/pkg/dev_compiler/lib/src/codegen/js_codegen.dart @@ -226,11 +226,13 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator { module ]); - var jsBin = compiler.options.runnerOptions.v8Binary; - - String scriptTag = null; - if (library.library.scriptTag != null) scriptTag = '/usr/bin/env $jsBin'; - return new JS.Program([moduleDef], scriptTag: scriptTag); + // TODO(jmesserly): scriptTag support. + // Enable this if we know we're targetting command line environment? + // It doesn't work in browser. + // var jsBin = compiler.options.runnerOptions.v8Binary; + // String scriptTag = null; + // if (library.library.scriptTag != null) scriptTag = '/usr/bin/env $jsBin'; + return new JS.Program([moduleDef]); } void _emitModuleItem(AstNode node) { @@ -3191,6 +3193,10 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator { name = 'set'; } else if (name == '-' && unary) { name = 'unary-'; + } else if (name == 'constructor' || name == 'prototype') { + // This uses an illegal (in Dart) character for a member, avoiding the + // conflict. We could use practically any character for this. + name = '+$name'; } // Dart "extension" methods. Used for JS Array, Boolean, Number, String. diff --git a/pkg/dev_compiler/lib/src/js/builder.dart b/pkg/dev_compiler/lib/src/js/builder.dart index f215da214a67..affcffea42ab 100644 --- a/pkg/dev_compiler/lib/src/js/builder.dart +++ b/pkg/dev_compiler/lib/src/js/builder.dart @@ -298,17 +298,25 @@ class JsBuilder { LiteralString escapedString(String value, [String quote = '"']) { // Start by escaping the backslashes. String escaped = value.replaceAll('\\', '\\\\'); - // Do not escape unicode characters and ' because they are allowed in the - // string literal anyway. - var re = new RegExp('\n|\r|$quote|\b|\f|\t|\v'); + + // http://www.ecma-international.org/ecma-262/6.0/#sec-literals-string-literals + // > All code points may appear literally in a string literal except for the + // > closing quote code points, U+005C (REVERSE SOLIDUS), + // > U+000D (CARRIAGE RETURN), U+2028 (LINE SEPARATOR), + // > U+2029 (PARAGRAPH SEPARATOR), and U+000A (LINE FEED). + var re = new RegExp('\n|\r|$quote|\b|\f|\t|\v|\u2028|\u2029'); escaped = escaped.replaceAllMapped(re, (m) { switch (m.group(0)) { case "\n" : return r"\n"; case "\r" : return r"\r"; + case "\u2028": return r"\u2028"; + case "\u2029": return r"\u2029"; // Quotes are only replaced if they conflict with the containing quote case '"': return r'\"'; case "'": return r"\'"; case "`": return r"\`"; + // TODO(jmesserly): these don't need to be escaped for correctness, + // but they are conventionally escaped. case "\b" : return r"\b"; case "\t" : return r"\t"; case "\f" : return r"\f"; diff --git a/pkg/dev_compiler/test/browser/language_tests.js b/pkg/dev_compiler/test/browser/language_tests.js index b6405cd81dca..17ea4fd9d757 100644 --- a/pkg/dev_compiler/test/browser/language_tests.js +++ b/pkg/dev_compiler/test/browser/language_tests.js @@ -35,13 +35,18 @@ } } - suite('scoping', () => { + suite('scopes and names', () => { dartLanguageTests([ 'implicit_scope_test', - ['built_in_identifier_test', 'none', 1] + ['built_in_identifier_test', 'none', 1], + 'naming3_test' ]); }); + suite('strings', () => { + dartLanguageTests(['optimized_string_charcodeat_test']); + }); + suite('method binding', () => { dartLanguageTests([ ['super_bound_closure_test', 'none'], diff --git a/pkg/dev_compiler/test/codegen/expect/html_input.html b/pkg/dev_compiler/test/codegen/expect/html_input.html index e04f195111c3..96ed534e35c0 100644 --- a/pkg/dev_compiler/test/codegen/expect/html_input.html +++ b/pkg/dev_compiler/test/codegen/expect/html_input.html @@ -27,10 +27,10 @@ - - + + diff --git a/pkg/dev_compiler/test/codegen/expect/script.js b/pkg/dev_compiler/test/codegen/expect/script.js index 6fec58333899..d053c285ec6e 100755 --- a/pkg/dev_compiler/test/codegen/expect/script.js +++ b/pkg/dev_compiler/test/codegen/expect/script.js @@ -1,4 +1,3 @@ -#!/usr/bin/env iojs dart_library.library('script', null, /* Imports */[ "dart_runtime/dart", 'dart/core' diff --git a/pkg/dev_compiler/test/codegen/expect/sunflower/sunflower.html b/pkg/dev_compiler/test/codegen/expect/sunflower/sunflower.html index 62c60f7fade3..aab058cab73a 100644 --- a/pkg/dev_compiler/test/codegen/expect/sunflower/sunflower.html +++ b/pkg/dev_compiler/test/codegen/expect/sunflower/sunflower.html @@ -51,8 +51,8 @@

drfibonacci's Sunflower Spectacular

- + diff --git a/pkg/dev_compiler/test/codegen/language/naming3_test.dart b/pkg/dev_compiler/test/codegen/language/naming3_test.dart new file mode 100644 index 000000000000..5f7c80fa5ae9 --- /dev/null +++ b/pkg/dev_compiler/test/codegen/language/naming3_test.dart @@ -0,0 +1,47 @@ +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import "package:expect/expect.dart"; + +class A { + var __PROTO__ = 499; + var constructor = 1; + var prototype = 2; +} + +// TODO(jmesserly): changed this test to avoid shadowing a field with a getter, +// which DDC doesn't currently support, see: +// https://github.com/dart-lang/dev_compiler/issues/52 +class A2 { + get __PROTO__ => 499; + get constructor => 1; + get prototype => 2; +} + +class B extends A2 { + get __PROTO__ => 42; + get constructor => 3; + get prototype => 4; +} + +main() { + var a = new A(); + var a2 = new A2(); + var b = new B(); + var list = [a, a2, b]; + for (int i = 0; i < list.length; i++) { + var proto = list[i].__PROTO__; + var constructor = list[i].constructor; + var prototype = list[i].prototype; + if (i < 2) { + Expect.equals(499, proto); + Expect.equals(1, constructor); + Expect.equals(2, prototype); + } else { + Expect.equals(42, proto); + Expect.equals(3, constructor); + Expect.equals(4, prototype); + } + } +} diff --git a/pkg/dev_compiler/test/codegen/language/optimized_string_charcodeat_test.dart b/pkg/dev_compiler/test/codegen/language/optimized_string_charcodeat_test.dart new file mode 100644 index 000000000000..98f4397dc0be --- /dev/null +++ b/pkg/dev_compiler/test/codegen/language/optimized_string_charcodeat_test.dart @@ -0,0 +1,81 @@ +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. +// VMOptions=--optimization-counter-threshold=10 --no-use-osr + +// Test optimized CodeUnitAt and array access. + +import "package:expect/expect.dart"; + + +String one_byte = "hest"; +String two_byte = "h\u{2029}ns"; + +int testOneByteCodeUnitAt(String x, int j) { + int test() { + return x.codeUnitAt(j); + } + for (int i = 0; i < 20; i++) test(); + return test(); +} + + +int testTwoByteCodeUnitAt(String x, int j) { + int test() { + return x.codeUnitAt(j); + } + for (int i = 0; i < 20; i++) test(); + return test(); +} + + +int testConstantStringCodeUnitAt(int j) { + int test() { + return "høns".codeUnitAt(j); + } + for (int i = 0; i < 20; i++) test(); + return test(); +} + + +int testConstantIndexCodeUnitAt(String x) { + int test() { + return x.codeUnitAt(1); + } + for (int i = 0; i < 20; i++) test(); + return test(); +} + + +int testOneByteCodeUnitAtInLoop(var x) { + var result = 0; + for (int i = 0; i < x.length; i++) { + result += x.codeUnitAt(i); + } + return result; +} + + +int testTwoByteCodeUnitAtInLoop(var x) { + var result = 0; + for (int i = 0; i < x.length; i++) { + result += x.codeUnitAt(i); + } + return result; +} + + +main() { + for (int j = 0; j < 10; j++) { + Expect.equals(101, testOneByteCodeUnitAt(one_byte, 1)); + Expect.equals(8233, testTwoByteCodeUnitAt(two_byte, 1)); + Expect.equals(248, testConstantStringCodeUnitAt(1)); + Expect.equals(101, testConstantIndexCodeUnitAt(one_byte)); + } + for (int j = 0; j < 20; j++) { + Expect.equals(436, testOneByteCodeUnitAtInLoop(one_byte)); + Expect.equals(8562, testTwoByteCodeUnitAtInLoop(two_byte)); + } + Expect.throws(() => testOneByteCodeUnitAtInLoop(123)); + Expect.throws(() => testTwoByteCodeUnitAtInLoop(123)); +}