Skip to content

Commit

Permalink
Add a @JSExportName annotation for internal use in the runtime (use…
Browse files Browse the repository at this point in the history
… it to export dart.assert instead of assert_)

BUG=
[email protected]

Review URL: https://codereview.chromium.org/1580413002 .
  • Loading branch information
ochafik committed Jan 19, 2016
1 parent bccc3c2 commit 51c3bcb
Show file tree
Hide file tree
Showing 8 changed files with 70 additions and 18 deletions.
2 changes: 1 addition & 1 deletion pkg/dev_compiler/lib/runtime/dart/_classes.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ dart_library.library('dart/_classes', null, /* Imports */[
], function(exports, dart_utils, core, _interceptors, types, rtti) {
'use strict';

const assert = dart_utils.assert_;
const assert = dart_utils.assert;
const copyProperties = dart_utils.copyProperties;
const copyTheseProperties = dart_utils.copyTheseProperties;
const defineMemoizedGetter = dart_utils.defineMemoizedGetter;
Expand Down
9 changes: 9 additions & 0 deletions pkg/dev_compiler/lib/runtime/dart/_foreign_helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ dart_library.library('dart/_foreign_helper', null, /* Imports */[
if (arg11 === void 0) arg11 = null;
}
dart.fn(JS, dart.dynamic, [core.String, core.String], [dart.dynamic, dart.dynamic, dart.dynamic, dart.dynamic, dart.dynamic, dart.dynamic, dart.dynamic, dart.dynamic, dart.dynamic, dart.dynamic, dart.dynamic, dart.dynamic]);
class JSExportName extends core.Object {
JSExportName(name) {
this.name = name;
}
}
dart.setSignature(JSExportName, {
constructors: () => ({JSExportName: [JSExportName, [core.String]]})
});
function JS_CURRENT_ISOLATE_CONTEXT() {
}
dart.fn(JS_CURRENT_ISOLATE_CONTEXT, () => dart.definiteFunctionType(IsolateContext, []));
Expand Down Expand Up @@ -111,6 +119,7 @@ dart_library.library('dart/_foreign_helper', null, /* Imports */[
dart.fn(JS_STRING_CONCAT, core.String, [core.String, core.String]);
// Exports:
exports.JS = JS;
exports.JSExportName = JSExportName;
exports.JS_CURRENT_ISOLATE_CONTEXT = JS_CURRENT_ISOLATE_CONTEXT;
exports.IsolateContext = IsolateContext;
exports.JS_CALL_IN_ISOLATE = JS_CALL_IN_ISOLATE;
Expand Down
2 changes: 1 addition & 1 deletion pkg/dev_compiler/lib/runtime/dart/_types.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ dart_library.library('dart/_types', null, /* Imports */[

const getOwnPropertyNames = Object.getOwnPropertyNames;

const assert = dart_utils.assert_;
const assert = dart_utils.assert;

/**
* Types in dart are represented at runtime as follows.
Expand Down
4 changes: 2 additions & 2 deletions pkg/dev_compiler/lib/runtime/dart/_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ dart_library.library('dart/_utils', null, /* Imports */[
function throwInternalError(message) {
throw Error(message);
}
function assert_(condition) {
function assert(condition) {
if (!condition) throwInternalError("The compiler is broken: failed assert");
}
function getOwnNamesAndSymbols(obj) {
Expand Down Expand Up @@ -95,7 +95,7 @@ dart_library.library('dart/_utils', null, /* Imports */[
exports.StrongModeError = StrongModeError;
exports.throwStrongModeError = throwStrongModeError;
exports.throwInternalError = throwInternalError;
exports.assert_ = assert_;
exports.assert = assert;
exports.getOwnNamesAndSymbols = getOwnNamesAndSymbols;
exports.safeGetOwnProperty = safeGetOwnProperty;
exports.defineLazyProperty = defineLazyProperty;
Expand Down
30 changes: 22 additions & 8 deletions pkg/dev_compiler/lib/src/codegen/js_codegen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1294,6 +1294,17 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
node.element);
}

/// Returns the name value of the `JSExportName` annotation (when compiling
/// the SDK), or `null` if there's none. This is used to control the name
/// under which functions are compiled and exported.
String _getJSExportName(Element e) {
if (e is! FunctionElement || !currentLibrary.source.isInSystemLibrary) {
return null;
}
var jsName = findAnnotation(e, isJSExportNameAnnotation);
return getConstantField(jsName, 'name', types.stringType)?.toStringValue();
}

@override
JS.Statement visitFunctionDeclaration(FunctionDeclaration node) {
assert(node.parent is CompilationUnit);
Expand All @@ -1309,7 +1320,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
var body = <JS.Statement>[];
_flushLibraryProperties(body);

var name = node.name.name;
var name = _getJSExportName(node.element) ?? node.name.name;

var fn = _visit(node.functionExpression);
bool needsTagging = true;
Expand Down Expand Up @@ -1575,8 +1586,6 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {

_loader.declareBeforeUse(element);

var name = element.name;

// type literal
if (element is ClassElement ||
element is DynamicElementImpl ||
Expand All @@ -1587,9 +1596,11 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {

// library member
if (element.enclosingElement is CompilationUnitElement) {
return _maybeQualifiedName(element);
return _emitTopLevelName(element);
}

var name = element.name;

// Unqualified class member. This could mean implicit-this, or implicit
// call to a static from the same class.
if (element is ClassMemberElement && element is! ConstructorElement) {
Expand Down Expand Up @@ -1757,17 +1768,17 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
jsArgs = [];
}
if (jsArgs != null) {
var genericName = _maybeQualifiedName(element, '$name\$');
var genericName = _emitTopLevelName(element, suffix: '\$');
return js.call('#(#)', [genericName, jsArgs]);
}
}

return _maybeQualifiedName(element);
return _emitTopLevelName(element);
}

JS.Expression _maybeQualifiedName(Element e, [String name]) {
JS.Expression _emitTopLevelName(Element e, {String suffix : ''}) {
var libName = _libraryName(e.library);
var nameExpr = _propertyName(name ?? e.name);
var nameExpr = _propertyName((_getJSExportName(e) ?? e.name) + suffix);

// Always qualify:
// * mutable top-level fields
Expand Down Expand Up @@ -2231,6 +2242,9 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
if (isJSTopLevel) eagerInit = true;

var fieldName = field.name.name;
if (element is TopLevelVariableElement) {
fieldName = _getJSExportName(element) ?? fieldName;
}
if ((field.isConst && eagerInit && element is TopLevelVariableElement) ||
isJSTopLevel) {
// constant fields don't change, so we can generate them as `let`
Expand Down
29 changes: 24 additions & 5 deletions pkg/dev_compiler/lib/src/codegen/js_interop.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,40 @@ import 'package:analyzer/src/generated/constant.dart';
bool _isJsLibType(String expectedName, Element e) =>
e?.name == expectedName && _isJsLib(e.library);

/// Returns true if [e] represents any library from `package:js` or is the
/// internal `dart:_js_helper` library.
bool _isJsLib(LibraryElement e) {
var libName = e?.name;
return libName == 'js' ||
libName == 'js.varargs' ||
libName == 'dart._js_helper';
if (e == null) return false;
var uri = e.source.uri;
if (uri.scheme == 'package' && uri.path.startsWith('js/')) return true;
if (uri.scheme == 'dart') {
return uri.path == '_js_helper' || uri.path == '_foreign_helper';
}
return false;
}

/// Whether [value] is a `@rest` annotation (to be used on function parameters
/// to have them compiled as `...` rest params in ES6 outputs).
bool isJsRestAnnotation(DartObjectImpl value) =>
_isJsLibType('_Rest', value.type.element);

/// Whether [i] is a `spread` invocation (to be used on function arguments
/// to have them compiled as `...` spread args in ES6 outputs).
bool isJsSpreadInvocation(MethodInvocation i) =>
_isJsLibType('spread', i.methodName?.bestElement);

// TODO(jmesserly): Move JsPeerInterface to package:js (see issue #135).
bool isJSAnnotation(DartObjectImpl value) => value.type.name == 'JS';
bool isJSAnnotation(DartObjectImpl value) =>
_isJsLibType('JS', value.type.element);

/// Whether [value] is a `@JSExportName` (internal annotation used in SDK
/// instead of `@JS` from `package:js`).
bool isJSExportNameAnnotation(DartObjectImpl value) {
var e = value?.type?.element;
if (e?.name != 'JSExportName') return false;
var uri = e.source.uri;
return uri.scheme == 'dart' && uri.path == '_foreign_helper';
}

bool isJsPeerInterface(DartObjectImpl value) =>
value.type.name == 'JsPeerInterface';
9 changes: 9 additions & 0 deletions pkg/dev_compiler/tool/input_sdk/private/foreign_helper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,15 @@ JS(String typeDescription, String codeTemplate,
[arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11])
{}

/// Annotates the compiled Js name for fields and methods.
/// Similar behaviour to `JS` from `package:js/js.dart` (but usable from runtime
/// files), and not to be confused with `JSName` from `js_helper` (which deals
/// with names of externs).
class JSExportName {
final String name;
const JSExportName(this.name);
}

/**
* Returns the isolate in which this code is running.
*/
Expand Down
3 changes: 2 additions & 1 deletion pkg/dev_compiler/tool/input_sdk/private/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

library dart._utils;

import 'dart:_foreign_helper' show JS;
import 'dart:_foreign_helper' show JS, JSExportName;

/// This library defines a set of general javascript utilities for us
/// by the Dart runtime.
Expand Down Expand Up @@ -39,6 +39,7 @@ void throwInternalError(String message) => JS('', '''(() => {

// TODO(ochafik): Re-introduce a @JS annotation in the SDK (same as package:js)
// so that this is named 'assert' in JavaScript.
@JSExportName('assert')
void assert_(bool condition) => JS('', '''(() => {
if (!condition) throwInternalError("The compiler is broken: failed assert");
})()''');
Expand Down

0 comments on commit 51c3bcb

Please sign in to comment.