Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(154)

Unified Diff: frog/var_member.dart

Issue 8746005: Fix a bunch of issues with 'hidden' DOM types. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: removed dead code Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: frog/var_member.dart
diff --git a/frog/var_member.dart b/frog/var_member.dart
index 0cce9184fe27d58100866ba9aaf5b1f39d259fe4..294c7898f2adb1183c5363e748b8f3dc88fc25a9 100644
--- a/frog/var_member.dart
+++ b/frog/var_member.dart
@@ -112,39 +112,59 @@ class VarFunctionStub extends VarMember {
class VarMethodStub extends VarMember {
final Member member;
final Arguments args;
- final Value body;
+ final String body;
VarMethodStub(String name, this.member, this.args, this.body): super(name);
+ bool get isHidden() =>
+ member != null ? member.declaringType.isHiddenNativeType : false;
+
Type get returnType() =>
member != null ? member.returnType : world.varType;
- String get typeName() =>
- member != null ? member.declaringType.jsname : 'Object';
+ Type get declaringType() =>
+ member != null ? member.declaringType : world.objectType;
void generate(CodeWriter code) {
- code.write('$typeName.prototype.$name = ');
- generateBody(code, ';');
- }
-
- void generateBody(CodeWriter code, String end) {
- if (_useDirectCall(member, args)) {
- code.writeln('$typeName.prototype.${member.jsname}$end');
+ code.write(world.gen._prototypeOf(declaringType, name) + ' = ');
+ if (!isHidden && _useDirectCall(args)) {
+ code.writeln('${declaringType.jsname}.prototype.${member.jsname};');
+ } else if (_needsExactTypeCheck()) {
+ code.enterBlock('function(${args.getCode()}) {');
+ code.enterBlock(
+ 'if (Object.getPrototypeOf(this).hasOwnProperty("$name")) {');
+ code.writeln('$body;');
+ code.exitBlock('}');
+ String argsCode = args.getCode();
+ if (argsCode != '') argsCode = ', ' + argsCode;
+ code.writeln('return Object.prototype.$name.call(this$argsCode);');
+ code.exitBlock('};');
} else {
code.enterBlock('function(${args.getCode()}) {');
- code.writeln('return ${body.code};');
- code.exitBlock('}$end');
+ code.writeln('$body;');
+ code.exitBlock('};');
}
}
- bool _useDirectCall(Member member, Arguments args) {
- // Create direct stubs when we can. We don't do this if the type is hidden,
- // i.e. we can't use "TypeName.prototype" to initialize. We also don't do it
- // for types like Object, that have native subtypes, otherwise things like
+ /**
+ * If we have a native method overridden by a hidden native method, we need to
+ * make sure the base one has an exact type test. Otherwise we don't need
+ * this.
+ */
+ bool _needsExactTypeCheck() {
+ if (member == null || member.declaringType.isObject) return false;
+
+ var members = member.declaringType.resolveMember(member.name).members;
+ return members.filter((m) => m != member
+ && m.declaringType.isHiddenNativeType).length >= 1;
+ }
+
+ bool _useDirectCall(Arguments args) {
+ // Create direct stubs when we can. We don't do this in some cases, such as
+ // types that have native subtypes (like Object), otherwise things like
// Object.prototype.toString$0 end up calling the toString on Object instead
// of on the derived type.
- if (member is MethodMember && !member.declaringType.isHiddenNativeType
- && !member.declaringType.hasNativeSubtypes) {
+ if (member is MethodMember && !member.declaringType.hasNativeSubtypes) {
MethodMember method = member;
if (method.needsArgumentConversion(args)) {
return false;
@@ -175,8 +195,7 @@ class VarMethodSet extends VarMember {
final Type returnType;
final Arguments args;
- /** The fallback stubs that need to be in our Object.prototype stub. */
- List<VarMethodStub> _fallbackStubs;
+ bool invoked = false;
VarMethodSet(String name, this.members, Arguments callArgs, this.returnType)
: super(name), args = callArgs.toCallStubArgs() {
@@ -185,83 +204,42 @@ class VarMethodSet extends VarMember {
/** The unmangled member name. */
String get baseName() => members[0].name;
- Value invoke(MethodGenerator context, Node node, Value target, Arguments args) {
+ Value invoke(MethodGenerator context, Node node, Value target,
+ Arguments args) {
_invokeMembers(context, node);
return super.invoke(context, node, target, args);
}
/** Invokes members to ensure they're generated. */
_invokeMembers(MethodGenerator context, Node node) {
- if (_fallbackStubs != null) return;
+ if (invoked) return;
+ invoked = true;
- var objectStub = null;
- _fallbackStubs = [];
+ bool hasObjectType = false;
for (var member in members) {
// Invoke the member with the stub args (this gives us the method body),
// then create the stub method.
- final target = new Value(member.declaringType, 'this', node.span);
+ final type = member.declaringType;
+ final target = new Value(type, 'this', node.span);
var result = member.invoke(context, node, target, args, isDynamic:true);
- var stub = new VarMethodStub(name, member, args, result);
-
- // Put the stub on the type directly if possible. Otherwise
- // put the stub on Object.prototype.
- var type = member.declaringType;
- if (type.isObject) {
- objectStub = stub;
- } else if (!type.isHiddenNativeType) {
- _addVarStub(type, stub);
- } else {
- _fallbackStubs.add(stub);
- }
+ var stub = new VarMethodStub(name, member, args, 'return ' + result.code);
+ type.varStubs[stub.name] = stub;
+
+ if (type.isObject) hasObjectType = true;
}
// Create a noSuchMethod fallback on Object if needed.
// Some methods, like toString and == already have a fallback on Object.
- if (objectStub == null) {
+ if (!hasObjectType) {
final target = new Value(world.objectType, 'this', node.span);
var result = target.invokeNoSuchMethod(context, baseName, node, args);
- objectStub = new VarMethodStub(name, null, args, result);
+ var stub = new VarMethodStub(name, null, args, 'return ' + result.code);
+ world.objectType.varStubs[stub.name] = stub;
}
- if (_fallbackStubs.length == 0) {
- _addVarStub(world.objectType, objectStub);
- } else {
- _fallbackStubs.add(objectStub);
- world.gen.corejs.useVarMethod = true;
- }
- }
-
- static _addVarStub(Type type, VarMember stub) {
- if (type.varStubs == null) type.varStubs = {};
- type.varStubs[stub.name] = stub;
}
- /**
- * Generate var call fallbacks, like this:
- *
- * $varMethod('addEventListener$1$capture', {
- * 'HTMLElement': function($0, capture) {
- * return this.addEventListener($0, capture);
- * },
- * 'SomeOtherDOMType': function($0, capture) {
- * return this.addEventListener($0, false, true, capture);
- * },
- * 'Object': function($0, capture) {
- * return this.noSuchMethod('addEventListener', [$0],
- * {'capture': capture});
- * }
- * });
- */
- void generate(CodeWriter code) {
- if (_fallbackStubs.length == 0) return;
-
- code.enterBlock('\$varMethod("$name", {');
- var lastOne = _fallbackStubs.last();
- for (var stub in _fallbackStubs) {
- code.write('"${stub.typeName}": ');
- stub.generateBody(code, stub == lastOne ? '' : ',');
- }
- code.exitBlock('});');
- }
+ // TODO(jmesserly): get rid of this as it's unused now
+ void generate(CodeWriter code) {}
}
String _getCallStubName(String name, Arguments args) {
@@ -271,3 +249,4 @@ String _getCallStubName(String name, Arguments args) {
}
return nameBuilder.toString();
}
+
« frog/lib/corelib.dart ('K') | « frog/value.dart ('k') | tests/language/language.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698