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

Unified Diff: pkg/compiler/lib/src/js_backend/js_interop_analysis.dart

Issue 1318043005: Support user generated custom native JS classes. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: ptal Created 5 years, 2 months 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: pkg/compiler/lib/src/js_backend/js_interop_analysis.dart
diff --git a/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart b/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart
new file mode 100644
index 0000000000000000000000000000000000000000..a7cd15176b08aa53229fd8307171495cd9fff955
--- /dev/null
+++ b/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart
@@ -0,0 +1,136 @@
+// Copyright (c) 2015, 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.
+
+/// Analysis to determine how to generate code for typed JavaScript interop.
+library compiler.src.js_backend.js_interop_analysis;
+
+import '../common/names.dart' show Identifiers;
+import '../compiler.dart' show Compiler;
+import '../diagnostics/messages.dart' show MessageKind;
+import '../constants/values.dart'
+ show
+ ConstantValue,
+ ConstructedConstantValue,
+ ListConstantValue,
+ NullConstantValue,
+ StringConstantValue,
+ TypeConstantValue;
+import '../elements/elements.dart'
+ show
+ ClassElement,
+ Element,
+ FieldElement,
+ FunctionElement,
+ LibraryElement,
+ MetadataAnnotation;
+
+import '../js/js.dart' as jsAst;
+import '../js/js.dart' show js;
+import '../universe/selector.dart' show Selector;
+import '../universe/universe.dart' show SelectorConstraints;
+
+import 'js_backend.dart' show JavaScriptBackend;
+
+class JsInteropAnalysis {
+ final JavaScriptBackend backend;
+
+ /// The resolved [FieldElement] for `Js.name`.
+ FieldElement nameField;
+ bool enabledJsInterop = false;
+
+ JsInteropAnalysis(this.backend);
+
+ void onQueueClosed() {
+ if (backend.jsAnnotationClass != null) {
+ nameField = backend.jsAnnotationClass.lookupMember('name');
+ backend.compiler.libraryLoader.libraries
+ .forEach(processJsInteropAnnotationsInLibrary);
+ }
+ }
+
+ void processJsInteropAnnotation(Element e) {
+ for (MetadataAnnotation annotation in e.implementation.metadata) {
+ ConstructedConstantValue constant =
+ backend.compiler.constants.getConstantValue(annotation.constant);
Siggi Cherem (dart-lang) 2015/10/13 02:08:53 check first for the type of constant since some an
Jacob 2015/10/13 03:10:42 Done.
+ if (constant != null &&
Siggi Cherem (dart-lang) 2015/10/13 02:08:53 since you'll have more than one check, consider do
Jacob 2015/10/13 03:10:42 done
+ constant.getType(backend.compiler.coreTypes).element ==
Siggi Cherem (dart-lang) 2015/10/13 02:08:53 or simply `constant.type.element` (I believe Const
Jacob 2015/10/13 03:10:43 Done.
+ backend.jsAnnotationClass) {
+ ConstantValue value = constant.fields[nameField];
+ if (value.isString) {
+ StringConstantValue stringValue = value;
+ e.setJsInteropName(stringValue.primitiveValue.slowToString());
+ } else {
+ assert(value.isNull);
+ e.setJsInteropName('');
+ }
+ enabledJsInterop = true;
+ return;
+ }
+ }
+ }
+
+ void processJsInteropAnnotationsInLibrary(LibraryElement library) {
+ processJsInteropAnnotation(library);
+ library.implementation.forEachLocalMember((Element element) {
+ processJsInteropAnnotation(element);
+ if (element.isClass) {
Siggi Cherem (dart-lang) 2015/10/13 02:08:53 nit: to keep the nesting level below smaller, we c
Jacob 2015/10/13 03:10:42 Done.
+ ClassElement classElement = element;
+ if (classElement.isJsInterop) {
+ classElement.forEachMember((_, memberElement) {
+ processJsInteropAnnotation(memberElement);
Siggi Cherem (dart-lang) 2015/10/13 02:08:53 could we move this down and combine with the body
Jacob 2015/10/13 03:10:42 moved it anyway. i think this is slightly as the
+ });
+
+ if (!classElement
+ .implementsInterface(backend.jsJavaScriptObjectClass)) {
+ backend.compiler.reportErrorMessage(classElement,
+ MessageKind.JS_INTEROP_CLASS_CANNOT_EXTEND_DART_CLASS, {
+ 'cls': classElement.name,
+ 'superclass': classElement.superclass.name
+ });
+ }
+
+ classElement.forEachMember(
+ (ClassElement classElement, Element member) {
+ if (!member.isSynthesized &&
+ classElement.isJsInterop &&
+ member is FunctionElement) {
+ FunctionElement fn = member;
+ if (!fn.isExternal && !fn.isAbstract) {
+ backend.compiler.reportErrorMessage(
+ fn,
+ MessageKind.JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER,
+ {'cls': classElement.name, 'member': member.name});
+ }
+ }
+ });
+ }
+ }
+ });
+ }
+
+ jsAst.Statement buildJsInteropBootstrap() {
+ if (!enabledJsInterop) return null;
+ List<jsAst.Statement> statements = <jsAst.Statement>[];
+ backend.compiler.codegenWorld.forEachInvokedName(
+ (String name, Map<Selector, SelectorConstraints> selectors) {
+ selectors.forEach((Selector selector, SelectorConstraints constraints) {
+ if (selector.isClosureCall) {
+ // TODO(jacobr): support named arguments.
+ if (selector.namedArgumentCount > 0) return;
+ int argumentCount = selector.argumentCount;
+ var candidateParameterNames =
+ 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLOMOPQRSTUVWXYZ';
+ var parameters = new List<String>.generate(
+ argumentCount, (i) => candidateParameterNames[i]);
+
+ var name = backend.namer.invocationName(selector);
+ statements.add(js.statement(
+ 'Function.prototype.# = function(#) { return this(#) }',
+ [name, parameters, parameters]));
+ }
+ });
+ });
+ return new jsAst.Block(statements);
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698