Skip to content

Commit

Permalink
Fixes #378
Browse files Browse the repository at this point in the history
Handles fields on "extension" types

See patch #1 for the test without the fix.

R=jmesserly@google.com

Review URL: https://codereview.chromium.org/1492523004 .
  • Loading branch information
vsmenon committed Dec 1, 2015
1 parent 8fb3eb3 commit a6f4d9b
Show file tree
Hide file tree
Showing 7 changed files with 351 additions and 8 deletions.
6 changes: 3 additions & 3 deletions pkg/dev_compiler/lib/src/codegen/js_codegen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
}

// Emit the signature on the class recording the runtime type information
var extensions = _extensionsToImplement(classElem);
{
var tStatics = <JS.Property>[];
var tMethods = <JS.Property>[];
Expand Down Expand Up @@ -827,7 +828,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
sigFields.add(build('statics', tStatics));
sigFields.add(aNames);
}
if (!sigFields.isEmpty) {
if (!sigFields.isEmpty || extensions.isNotEmpty) {
var sig = new JS.ObjectInitializer(sigFields);
var classExpr = new JS.Identifier(name);
body.add(js.statement('dart.setSignature(#, #);', [classExpr, sig]));
Expand All @@ -836,7 +837,6 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {

// If a concrete class implements one of our extensions, we might need to
// add forwarders.
var extensions = _extensionsToImplement(classElem);
if (extensions.isNotEmpty) {
var methodNames = <JS.Expression>[];
for (var e in extensions) {
Expand Down Expand Up @@ -3388,7 +3388,7 @@ class JSGenerator extends CodeGenerator {
// Clone the AST first, so we can mutate it.
unit = unit.clone();
var library = unit.library.element.library;
var fields = findFieldsNeedingStorage(unit);
var fields = findFieldsNeedingStorage(unit, _extensionTypes);
var codegen =
new JSCodegenVisitor(compiler, rules, library, _extensionTypes, fields);
var module = codegen.emitLibrary(unit);
Expand Down
16 changes: 11 additions & 5 deletions pkg/dev_compiler/lib/src/codegen/js_field_storage.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@ import '../info.dart' show LibraryUnit;

/// We use a storage slot for fields that override or can be overridden by
/// getter/setter pairs.
HashSet<FieldElement> findFieldsNeedingStorage(LibraryUnit library) {
HashSet<FieldElement> findFieldsNeedingStorage(
LibraryUnit library, HashSet<ClassElement> extensionTypes) {
var overrides = new HashSet<FieldElement>();
for (var unit in library.partsThenLibrary) {
for (var cls in unit.element.types) {
var superclasses = getSuperclasses(cls);
for (var field in cls.fields) {
if (!field.isSynthetic && !overrides.contains(field)) {
checkForPropertyOverride(field, superclasses, overrides);
checkForPropertyOverride(
field, superclasses, overrides, extensionTypes);
}
}
}
Expand All @@ -28,8 +30,11 @@ HashSet<FieldElement> findFieldsNeedingStorage(LibraryUnit library) {
return overrides;
}

void checkForPropertyOverride(FieldElement field,
List<ClassElement> superclasses, HashSet<FieldElement> overrides) {
void checkForPropertyOverride(
FieldElement field,
List<ClassElement> superclasses,
HashSet<FieldElement> overrides,
HashSet<ClassElement> extensionTypes) {
assert(!field.isSynthetic);

var library = field.library;
Expand All @@ -41,7 +46,8 @@ void checkForPropertyOverride(FieldElement field,
// If we find an abstract getter/setter pair, stop the search.
var getter = superprop.getter;
var setter = superprop.setter;
if ((getter == null || getter.isAbstract) &&
if (!extensionTypes.contains(superclass) &&
(getter == null || getter.isAbstract) &&
(setter == null || setter.isAbstract)) {
break;
}
Expand Down
299 changes: 299 additions & 0 deletions pkg/dev_compiler/test/codegen/expect/collection/src/comparators.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,299 @@
dart_library.library('collection/src/comparators', null, /* Imports */[
"dart/_runtime",
'dart/core'
], /* Lazy imports */[
], function(exports, dart, core) {
'use strict';
let dartx = dart.dartx;
const _zero = 48;
const _upperCaseA = 65;
const _upperCaseZ = 90;
const _lowerCaseA = 97;
const _lowerCaseZ = 122;
const _asciiCaseBit = 32;
function equalsIgnoreAsciiCase(a, b) {
if (a[dartx.length] != b[dartx.length])
return false;
for (let i = 0; dart.notNull(i) < dart.notNull(a[dartx.length]); i = dart.notNull(i) + 1) {
let aChar = a[dartx.codeUnitAt](i);
let bChar = b[dartx.codeUnitAt](i);
if (aChar == bChar)
continue;
if ((dart.notNull(aChar) ^ dart.notNull(bChar)) != _asciiCaseBit)
return false;
let aCharUpperCase = dart.notNull(aChar) | dart.notNull(_asciiCaseBit);
if (dart.notNull(_upperCaseA) <= dart.notNull(aCharUpperCase) && dart.notNull(aCharUpperCase) <= dart.notNull(_upperCaseZ)) {
continue;
}
return false;
}
return true;
}
dart.fn(equalsIgnoreAsciiCase, core.bool, [core.String, core.String]);
function hashIgnoreAsciiCase(string) {
let hash = 0;
for (let i = 0; dart.notNull(i) < dart.notNull(string[dartx.length]); i = dart.notNull(i) + 1) {
let char = string[dartx.codeUnitAt](i);
if (dart.notNull(_lowerCaseA) <= dart.notNull(char) && dart.notNull(char) <= dart.notNull(_lowerCaseZ)) {
char = dart.notNull(char) - dart.notNull(_asciiCaseBit);
}
hash = 536870911 & dart.notNull(hash) + dart.notNull(char);
hash = 536870911 & dart.notNull(hash) + ((524287 & dart.notNull(hash)) << 10);
hash = dart.notNull(hash) >> 6;
}
hash = 536870911 & dart.notNull(hash) + ((67108863 & dart.notNull(hash)) << 3);
hash = dart.notNull(hash) >> 11;
return 536870911 & dart.notNull(hash) + ((16383 & dart.notNull(hash)) << 15);
}
dart.fn(hashIgnoreAsciiCase, core.int, [core.String]);
function compareAsciiUpperCase(a, b) {
let defaultResult = 0;
for (let i = 0; dart.notNull(i) < dart.notNull(a[dartx.length]); i = dart.notNull(i) + 1) {
if (dart.notNull(i) >= dart.notNull(b[dartx.length]))
return 1;
let aChar = a[dartx.codeUnitAt](i);
let bChar = b[dartx.codeUnitAt](i);
if (aChar == bChar)
continue;
let aUpperCase = aChar;
let bUpperCase = bChar;
if (dart.notNull(_lowerCaseA) <= dart.notNull(aChar) && dart.notNull(aChar) <= dart.notNull(_lowerCaseZ)) {
aUpperCase = dart.notNull(aUpperCase) - dart.notNull(_asciiCaseBit);
}
if (dart.notNull(_lowerCaseA) <= dart.notNull(bChar) && dart.notNull(bChar) <= dart.notNull(_lowerCaseZ)) {
bUpperCase = dart.notNull(bUpperCase) - dart.notNull(_asciiCaseBit);
}
if (aUpperCase != bUpperCase)
return (dart.notNull(aUpperCase) - dart.notNull(bUpperCase))[dartx.sign];
if (defaultResult == 0)
defaultResult = dart.notNull(aChar) - dart.notNull(bChar);
}
if (dart.notNull(b[dartx.length]) > dart.notNull(a[dartx.length]))
return -1;
return defaultResult[dartx.sign];
}
dart.fn(compareAsciiUpperCase, core.int, [core.String, core.String]);
function compareAsciiLowerCase(a, b) {
let defaultResult = 0;
for (let i = 0; dart.notNull(i) < dart.notNull(a[dartx.length]); i = dart.notNull(i) + 1) {
if (dart.notNull(i) >= dart.notNull(b[dartx.length]))
return 1;
let aChar = a[dartx.codeUnitAt](i);
let bChar = b[dartx.codeUnitAt](i);
if (aChar == bChar)
continue;
let aLowerCase = aChar;
let bLowerCase = bChar;
if (dart.notNull(_upperCaseA) <= dart.notNull(bChar) && dart.notNull(bChar) <= dart.notNull(_upperCaseZ)) {
bLowerCase = dart.notNull(bLowerCase) + dart.notNull(_asciiCaseBit);
}
if (dart.notNull(_upperCaseA) <= dart.notNull(aChar) && dart.notNull(aChar) <= dart.notNull(_upperCaseZ)) {
aLowerCase = dart.notNull(aLowerCase) + dart.notNull(_asciiCaseBit);
}
if (aLowerCase != bLowerCase)
return (dart.notNull(aLowerCase) - dart.notNull(bLowerCase))[dartx.sign];
if (defaultResult == 0)
defaultResult = dart.notNull(aChar) - dart.notNull(bChar);
}
if (dart.notNull(b[dartx.length]) > dart.notNull(a[dartx.length]))
return -1;
return defaultResult[dartx.sign];
}
dart.fn(compareAsciiLowerCase, core.int, [core.String, core.String]);
function compareNatural(a, b) {
for (let i = 0; dart.notNull(i) < dart.notNull(a[dartx.length]); i = dart.notNull(i) + 1) {
if (dart.notNull(i) >= dart.notNull(b[dartx.length]))
return 1;
let aChar = a[dartx.codeUnitAt](i);
let bChar = b[dartx.codeUnitAt](i);
if (aChar != bChar) {
return _compareNaturally(a, b, i, aChar, bChar);
}
}
if (dart.notNull(b[dartx.length]) > dart.notNull(a[dartx.length]))
return -1;
return 0;
}
dart.fn(compareNatural, core.int, [core.String, core.String]);
function compareAsciiLowerCaseNatural(a, b) {
let defaultResult = 0;
for (let i = 0; dart.notNull(i) < dart.notNull(a[dartx.length]); i = dart.notNull(i) + 1) {
if (dart.notNull(i) >= dart.notNull(b[dartx.length]))
return 1;
let aChar = a[dartx.codeUnitAt](i);
let bChar = b[dartx.codeUnitAt](i);
if (aChar == bChar)
continue;
let aLowerCase = aChar;
let bLowerCase = bChar;
if (dart.notNull(_upperCaseA) <= dart.notNull(aChar) && dart.notNull(aChar) <= dart.notNull(_upperCaseZ)) {
aLowerCase = dart.notNull(aLowerCase) + dart.notNull(_asciiCaseBit);
}
if (dart.notNull(_upperCaseA) <= dart.notNull(bChar) && dart.notNull(bChar) <= dart.notNull(_upperCaseZ)) {
bLowerCase = dart.notNull(bLowerCase) + dart.notNull(_asciiCaseBit);
}
if (aLowerCase != bLowerCase) {
return _compareNaturally(a, b, i, aLowerCase, bLowerCase);
}
if (defaultResult == 0)
defaultResult = dart.notNull(aChar) - dart.notNull(bChar);
}
if (dart.notNull(b[dartx.length]) > dart.notNull(a[dartx.length]))
return -1;
return defaultResult[dartx.sign];
}
dart.fn(compareAsciiLowerCaseNatural, core.int, [core.String, core.String]);
function compareAsciiUpperCaseNatural(a, b) {
let defaultResult = 0;
for (let i = 0; dart.notNull(i) < dart.notNull(a[dartx.length]); i = dart.notNull(i) + 1) {
if (dart.notNull(i) >= dart.notNull(b[dartx.length]))
return 1;
let aChar = a[dartx.codeUnitAt](i);
let bChar = b[dartx.codeUnitAt](i);
if (aChar == bChar)
continue;
let aUpperCase = aChar;
let bUpperCase = bChar;
if (dart.notNull(_lowerCaseA) <= dart.notNull(aChar) && dart.notNull(aChar) <= dart.notNull(_lowerCaseZ)) {
aUpperCase = dart.notNull(aUpperCase) - dart.notNull(_asciiCaseBit);
}
if (dart.notNull(_lowerCaseA) <= dart.notNull(bChar) && dart.notNull(bChar) <= dart.notNull(_lowerCaseZ)) {
bUpperCase = dart.notNull(bUpperCase) - dart.notNull(_asciiCaseBit);
}
if (aUpperCase != bUpperCase) {
return _compareNaturally(a, b, i, aUpperCase, bUpperCase);
}
if (defaultResult == 0)
defaultResult = dart.notNull(aChar) - dart.notNull(bChar);
}
if (dart.notNull(b[dartx.length]) > dart.notNull(a[dartx.length]))
return -1;
return defaultResult[dartx.sign];
}
dart.fn(compareAsciiUpperCaseNatural, core.int, [core.String, core.String]);
function _compareNaturally(a, b, index, aChar, bChar) {
dart.assert(aChar != bChar);
let aIsDigit = _isDigit(aChar);
let bIsDigit = _isDigit(bChar);
if (dart.notNull(aIsDigit)) {
if (dart.notNull(bIsDigit)) {
return _compareNumerically(a, b, aChar, bChar, index);
} else if (dart.notNull(index) > 0 && dart.notNull(_isDigit(a[dartx.codeUnitAt](dart.notNull(index) - 1)))) {
return 1;
}
} else if (dart.notNull(bIsDigit) && dart.notNull(index) > 0 && dart.notNull(_isDigit(b[dartx.codeUnitAt](dart.notNull(index) - 1)))) {
return -1;
}
return (dart.notNull(aChar) - dart.notNull(bChar))[dartx.sign];
}
dart.fn(_compareNaturally, core.int, [core.String, core.String, core.int, core.int, core.int]);
function _compareNumerically(a, b, aChar, bChar, index) {
if (dart.notNull(_isNonZeroNumberSuffix(a, index))) {
let result = _compareDigitCount(a, b, index, index);
if (result != 0)
return result;
return (dart.notNull(aChar) - dart.notNull(bChar))[dartx.sign];
}
let aIndex = index;
let bIndex = index;
if (aChar == _zero) {
do {
aIndex = dart.notNull(aIndex) + 1;
if (aIndex == a[dartx.length])
return -1;
aChar = a[dartx.codeUnitAt](aIndex);
} while (aChar == _zero);
if (!dart.notNull(_isDigit(aChar)))
return -1;
} else if (bChar == _zero) {
do {
bIndex = dart.notNull(bIndex) + 1;
if (bIndex == b[dartx.length])
return 1;
bChar = b[dartx.codeUnitAt](bIndex);
} while (bChar == _zero);
if (!dart.notNull(_isDigit(bChar)))
return 1;
}
if (aChar != bChar) {
let result = _compareDigitCount(a, b, aIndex, bIndex);
if (result != 0)
return result;
return (dart.notNull(aChar) - dart.notNull(bChar))[dartx.sign];
}
while (true) {
let aIsDigit = false;
let bIsDigit = false;
aChar = 0;
bChar = 0;
if ((aIndex = dart.notNull(aIndex) + 1) < dart.notNull(a[dartx.length])) {
aChar = a[dartx.codeUnitAt](aIndex);
aIsDigit = _isDigit(aChar);
}
if ((bIndex = dart.notNull(bIndex) + 1) < dart.notNull(b[dartx.length])) {
bChar = b[dartx.codeUnitAt](bIndex);
bIsDigit = _isDigit(bChar);
}
if (dart.notNull(aIsDigit)) {
if (dart.notNull(bIsDigit)) {
if (aChar == bChar)
continue;
break;
}
return 1;
} else if (dart.notNull(bIsDigit)) {
return -1;
} else {
return (dart.notNull(aIndex) - dart.notNull(bIndex))[dartx.sign];
}
}
let result = _compareDigitCount(a, b, aIndex, bIndex);
if (result != 0)
return result;
return (dart.notNull(aChar) - dart.notNull(bChar))[dartx.sign];
}
dart.fn(_compareNumerically, core.int, [core.String, core.String, core.int, core.int, core.int]);
function _compareDigitCount(a, b, i, j) {
while ((i = dart.notNull(i) + 1) < dart.notNull(a[dartx.length])) {
let aIsDigit = _isDigit(a[dartx.codeUnitAt](i));
if ((j = dart.notNull(j) + 1) == b[dartx.length])
return dart.notNull(aIsDigit) ? 1 : 0;
let bIsDigit = _isDigit(b[dartx.codeUnitAt](j));
if (dart.notNull(aIsDigit)) {
if (dart.notNull(bIsDigit))
continue;
return 1;
} else if (dart.notNull(bIsDigit)) {
return -1;
} else {
return 0;
}
}
if ((j = dart.notNull(j) + 1) < dart.notNull(b[dartx.length]) && dart.notNull(_isDigit(b[dartx.codeUnitAt](j)))) {
return -1;
}
return 0;
}
dart.fn(_compareDigitCount, core.int, [core.String, core.String, core.int, core.int]);
function _isDigit(charCode) {
return (dart.notNull(charCode) ^ dart.notNull(_zero)) <= 9;
}
dart.fn(_isDigit, core.bool, [core.int]);
function _isNonZeroNumberSuffix(string, index) {
while ((index = dart.notNull(index) - 1) >= 0) {
let char = string[dartx.codeUnitAt](index);
if (char != _zero)
return _isDigit(char);
}
return false;
}
dart.fn(_isNonZeroNumberSuffix, core.bool, [core.String, core.int]);
// Exports:
exports.equalsIgnoreAsciiCase = equalsIgnoreAsciiCase;
exports.hashIgnoreAsciiCase = hashIgnoreAsciiCase;
exports.compareAsciiUpperCase = compareAsciiUpperCase;
exports.compareAsciiLowerCase = compareAsciiLowerCase;
exports.compareNatural = compareNatural;
exports.compareAsciiLowerCaseNatural = compareAsciiLowerCaseNatural;
exports.compareAsciiUpperCaseNatural = compareAsciiUpperCaseNatural;
});
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// Messages from compiling comparators.dart
Loading

0 comments on commit a6f4d9b

Please sign in to comment.