| Index: pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
|
| diff --git a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
|
| index d7e1578c9962a0ecc46ba159681e45a0fd10f593..366ede2e704e2271e54b6943d4f95c70e6ed3926 100644
|
| --- a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
|
| +++ b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
|
| @@ -111,4 +111,77 @@ class ClassStubGenerator {
|
|
|
| return generatedStubs;
|
| }
|
| +
|
| + Map<String, Selector> computeSelectorsForNsmHandlers() {
|
| +
|
| + Map<String, Selector> jsNames = <String, Selector>{};
|
| +
|
| + // Do not generate no such method handlers if there is no class.
|
| + if (compiler.codegenWorld.directlyInstantiatedClasses.isEmpty) {
|
| + return jsNames;
|
| + }
|
| +
|
| + void addNoSuchMethodHandlers(String ignore, Set<Selector> selectors) {
|
| + TypeMask objectSubclassTypeMask =
|
| + new TypeMask.subclass(compiler.objectClass, compiler.world);
|
| +
|
| + for (Selector selector in selectors) {
|
| + TypeMask mask = selector.mask;
|
| + if (mask == null) mask = objectSubclassTypeMask;
|
| +
|
| + if (!mask.needsNoSuchMethodHandling(selector, compiler.world)) {
|
| + continue;
|
| + }
|
| + String jsName = namer.invocationMirrorInternalName(selector);
|
| + jsNames[jsName] = selector;
|
| + }
|
| + }
|
| +
|
| + compiler.codegenWorld.invokedNames.forEach(addNoSuchMethodHandlers);
|
| + compiler.codegenWorld.invokedGetters.forEach(addNoSuchMethodHandlers);
|
| + compiler.codegenWorld.invokedSetters.forEach(addNoSuchMethodHandlers);
|
| + return jsNames;
|
| + }
|
| +
|
| + jsAst.Expression generateStubForNoSuchMethod(Selector selector) {
|
| + // Values match JSInvocationMirror in js-helper library.
|
| + int type = selector.invocationMirrorKind;
|
| + List<String> parameterNames =
|
| + new List.generate(selector.argumentCount, (i) => '\$$i');
|
| +
|
| + List<jsAst.Expression> argNames =
|
| + selector.getOrderedNamedArguments().map((String name) =>
|
| + js.string(name)).toList();
|
| +
|
| + String methodName = selector.invocationMirrorMemberName;
|
| + String internalName = namer.invocationMirrorInternalName(selector);
|
| +
|
| + assert(backend.isInterceptedName(Compiler.NO_SUCH_METHOD));
|
| + jsAst.Expression expression =
|
| + js('''this.#noSuchMethodName(this,
|
| + #createInvocationMirror(#methodName,
|
| + #internalName,
|
| + #type,
|
| + #arguments,
|
| + #namedArguments))''',
|
| + {'noSuchMethodName': namer.noSuchMethodName,
|
| + 'createInvocationMirror':
|
| + backend.emitter.staticFunctionAccess(
|
| + backend.getCreateInvocationMirror()),
|
| + 'methodName':
|
| + js.string(compiler.enableMinification
|
| + ? internalName : methodName),
|
| + 'internalName': js.string(internalName),
|
| + 'type': js.number(type),
|
| + 'arguments':
|
| + new jsAst.ArrayInitializer(parameterNames.map(js).toList()),
|
| + 'namedArguments': new jsAst.ArrayInitializer(argNames)});
|
| +
|
| + if (backend.isInterceptedName(selector.name)) {
|
| + return js(r'function($receiver, #) { return # }',
|
| + [parameterNames, expression]);
|
| + } else {
|
| + return js(r'function(#) { return # }', [parameterNames, expression]);
|
| + }
|
| + }
|
| }
|
|
|