Skip to content
This repository was archived by the owner on Feb 22, 2018. It is now read-only.

Commit ae54046

Browse files
author
Olivier Chafik
committed
Special-case top-level final JS fields to make them non-lazy
(follow-up to John's suggestion in https://codereview.chromium.org/1486473002/) BUG= [email protected] Review URL: https://codereview.chromium.org/1487213002 .
1 parent c9d909c commit ae54046

File tree

6 files changed

+46
-58
lines changed

6 files changed

+46
-58
lines changed

lib/runtime/dart/_isolate_helper.js

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -914,14 +914,10 @@ dart_library.library('dart/_isolate_helper', null, /* Imports */[
914914
constructors: () => ({_IsolateEvent: [_IsolateEvent, [_IsolateContext, core.Function, core.String]]}),
915915
methods: () => ({process: [dart.void, []]})
916916
});
917-
dart.defineLazyProperties(exports, {
918-
get _global() {
919-
return typeof global == 'undefined' ? self : global;
920-
}
921-
});
917+
const _global = typeof global == 'undefined' ? self : global;
922918
class _MainManagerStub extends core.Object {
923919
postMessage(msg) {
924-
exports._global.postMessage(msg);
920+
_global.postMessage(msg);
925921
}
926922
}
927923
dart.setSignature(_MainManagerStub, {
@@ -931,13 +927,13 @@ dart_library.library('dart/_isolate_helper', null, /* Imports */[
931927
const _SPAWN_FAILED_SIGNAL = "spawn failed";
932928
dart.copyProperties(exports, {
933929
get globalWindow() {
934-
return exports._global.window;
930+
return _global.window;
935931
},
936932
get globalWorker() {
937-
return exports._global.Worker;
933+
return _global.Worker;
938934
},
939935
get globalPostMessageDefined() {
940-
return !!exports._global.postMessage;
936+
return !!_global.postMessage;
941937
}
942938
});
943939
const _MainFunction = dart.typedef('_MainFunction', () => dart.functionType(dart.dynamic, []));

lib/runtime/dart/_js_mirrors.js

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,24 +28,18 @@ dart_library.library('dart/_js_mirrors', null, /* Imports */[
2828
return new JsClassMirror._(key);
2929
}
3030
dart.fn(reflectType, mirrors.TypeMirror, [core.Type]);
31-
dart.defineLazyProperties(exports, {
32-
get _dart() {
33-
return dart;
34-
},
35-
get _metadata() {
36-
return exports._dart.metadata;
37-
}
38-
});
31+
const _dart = dart;
32+
const _metadata = _dart.metadata;
3933
function _dload(obj, name) {
40-
return exports._dart.dload(obj, name);
34+
return _dart.dload(obj, name);
4135
}
4236
dart.fn(_dload, dart.dynamic, [dart.dynamic, core.String]);
4337
function _dput(obj, name, val) {
44-
exports._dart.dput(obj, name, val);
38+
_dart.dput(obj, name, val);
4539
}
4640
dart.fn(_dput, dart.void, [dart.dynamic, core.String, dart.dynamic]);
4741
function _dsend(obj, name, args) {
48-
return exports._dart.dsend(obj, name, ...args);
42+
return _dart.dsend(obj, name, ...args);
4943
}
5044
dart.fn(_dsend, dart.dynamic, [dart.dynamic, core.String, core.List]);
5145
const _toJsMap = Symbol('_toJsMap');
@@ -103,23 +97,23 @@ dart_library.library('dart/_js_mirrors', null, /* Imports */[
10397
[_toJsMap]: [dart.dynamic, [core.Map$(core.Symbol, dart.dynamic)]]
10498
})
10599
});
106-
const _metadata = Symbol('_metadata');
100+
const _metadata$ = Symbol('_metadata');
107101
const _declarations = Symbol('_declarations');
108102
const _cls = Symbol('_cls');
109103
class JsClassMirror extends core.Object {
110104
get metadata() {
111-
return this[_metadata];
105+
return this[_metadata$];
112106
}
113107
get declarations() {
114108
return this[_declarations];
115109
}
116110
_(cls) {
117111
this[_cls] = cls;
118112
this.simpleName = core.Symbol.new(cls.name);
119-
this[_metadata] = null;
113+
this[_metadata$] = null;
120114
this[_declarations] = null;
121115
let fn = this[_cls][dart.metadata];
122-
this[_metadata] = fn == null ? dart.list([], mirrors.InstanceMirror) : core.List$(mirrors.InstanceMirror).from(dart.as(dart.dsend(dart.dcall(fn), 'map', dart.fn(i => new JsInstanceMirror._(i), JsInstanceMirror, [dart.dynamic])), core.Iterable));
116+
this[_metadata$] = fn == null ? dart.list([], mirrors.InstanceMirror) : core.List$(mirrors.InstanceMirror).from(dart.as(dart.dsend(dart.dcall(fn), 'map', dart.fn(i => new JsInstanceMirror._(i), JsInstanceMirror, [dart.dynamic])), core.Iterable));
123117
this[_declarations] = core.Map$(core.Symbol, mirrors.MethodMirror).new();
124118
this[_declarations].set(this.simpleName, new JsMethodMirror._(this, this[_cls]));
125119
}
@@ -344,7 +338,7 @@ dart_library.library('dart/_js_mirrors', null, /* Imports */[
344338
this[_method] = method;
345339
this[_name] = getName(cls.simpleName);
346340
this[_params] = null;
347-
let ftype = exports._dart.classGetConstructorType(cls[_cls]);
341+
let ftype = _dart.classGetConstructorType(cls[_cls]);
348342
this[_params] = this[_createParameterMirrorList](ftype);
349343
}
350344
get constructorName() {

lib/runtime/dart/js.js

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -334,9 +334,9 @@ dart_library.library('dart/js', null, /* Imports */[
334334
} else if (dart.is(o, JsObject)) {
335335
return dart.dload(o, _jsObject);
336336
} else if (dart.is(o, core.Function)) {
337-
return _putIfAbsent(exports._jsProxies, o, _wrapDartFunction);
337+
return _putIfAbsent(_jsProxies, o, _wrapDartFunction);
338338
} else {
339-
return _putIfAbsent(exports._jsProxies, o, dart.fn(o => new _DartObject(o), _DartObject, [dart.dynamic]));
339+
return _putIfAbsent(_jsProxies, o, dart.fn(o => new _DartObject(o), _DartObject, [dart.dynamic]));
340340
}
341341
}
342342
dart.fn(_convertToJS);
@@ -345,7 +345,7 @@ dart_library.library('dart/js', null, /* Imports */[
345345
let args = Array.prototype.map.call(arguments, _convertToDart);
346346
return _convertToJS(f(...args));
347347
};
348-
dart.dsetindex(exports._dartProxies, wrapper, f);
348+
dart.dsetindex(_dartProxies, wrapper, f);
349349
return wrapper;
350350
}
351351
dart.fn(_wrapDartFunction);
@@ -358,7 +358,7 @@ dart_library.library('dart/js', null, /* Imports */[
358358
} else if (dart.is(o, _DartObject) && dart.jsobject != dart.realRuntimeType(o)) {
359359
return dart.dload(o, _dartObj);
360360
} else {
361-
return _putIfAbsent(exports._dartProxies, o, _wrapToDart);
361+
return _putIfAbsent(_dartProxies, o, _wrapToDart);
362362
}
363363
}
364364
dart.fn(_convertToDart, core.Object, [dart.dynamic]);
@@ -372,14 +372,8 @@ dart_library.library('dart/js', null, /* Imports */[
372372
return new JsObject._fromJs(o);
373373
}
374374
dart.fn(_wrapToDart, JsObject, [dart.dynamic]);
375-
dart.defineLazyProperties(exports, {
376-
get _dartProxies() {
377-
return new WeakMap();
378-
},
379-
get _jsProxies() {
380-
return new WeakMap();
381-
}
382-
});
375+
const _dartProxies = new WeakMap();
376+
const _jsProxies = new WeakMap();
383377
function _putIfAbsent(weakMap, o, getValue) {
384378
let value = weakMap.get(o);
385379
if (value == null) {

lib/src/codegen/js_codegen.dart

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1325,23 +1325,23 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
13251325
}
13261326

13271327
bool _isInlineJSFunction(FunctionExpression functionExpression) {
1328-
bool isJsInvocation(Expression expr) =>
1329-
expr is MethodInvocation && isInlineJS(expr.methodName.staticElement);
1330-
13311328
var body = functionExpression.body;
13321329
if (body is ExpressionFunctionBody) {
1333-
return isJsInvocation(body.expression);
1330+
return _isJSInvocation(body.expression);
13341331
} else if (body is BlockFunctionBody) {
13351332
if (body.block.statements.length == 1) {
13361333
var stat = body.block.statements.single;
13371334
if (stat is ReturnStatement) {
1338-
return isJsInvocation(stat.expression);
1335+
return _isJSInvocation(stat.expression);
13391336
}
13401337
}
13411338
}
13421339
return false;
13431340
}
13441341

1342+
bool _isJSInvocation(Expression expr) =>
1343+
expr is MethodInvocation && isInlineJS(expr.methodName.staticElement);
1344+
13451345
// Simplify `(args) => ((x, y) => { ... })(x, y)` to `(args) => { ... }`.
13461346
// Note: we don't check if the top-level args match the ones passed through
13471347
// the arrow function, which allows silently passing args through to the
@@ -1753,7 +1753,9 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
17531753
// Always qualify:
17541754
// * mutable top-level fields
17551755
// * elements from other libraries
1756-
bool mutableTopLevel = e is TopLevelVariableElement && !e.isConst;
1756+
bool mutableTopLevel = e is TopLevelVariableElement &&
1757+
!e.isConst &&
1758+
!_isFinalJSDecl(e.computeNode());
17571759
bool fromAnotherLibrary = e.library != currentLibrary;
17581760
if (mutableTopLevel || fromAnotherLibrary) {
17591761
return new JS.PropertyAccess(libName, nameExpr);
@@ -2160,6 +2162,10 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
21602162
return new JS.VariableInitialization(name, _visitInitializer(node));
21612163
}
21622164

2165+
bool _isFinalJSDecl(AstNode field) => field is VariableDeclaration &&
2166+
field.isFinal &&
2167+
_isJSInvocation(field.initializer);
2168+
21632169
/// Emits a static or top-level field.
21642170
JS.Statement _emitStaticField(VariableDeclaration field) {
21652171
PropertyInducingElement element = field.element;
@@ -2178,8 +2184,14 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
21782184
eagerInit = false;
21792185
}
21802186

2187+
// Treat `final x = JS('', '...')` as a const (non-lazy) to help compile
2188+
// runtime helpers.
2189+
var isJSTopLevel = field.isFinal && _isFinalJSDecl(field);
2190+
if (isJSTopLevel) eagerInit = true;
2191+
21812192
var fieldName = field.name.name;
2182-
if (field.isConst && eagerInit && element is TopLevelVariableElement) {
2193+
if ((field.isConst && eagerInit && element is TopLevelVariableElement) ||
2194+
isJSTopLevel) {
21832195
// constant fields don't change, so we can generate them as `let`
21842196
// but add them to the module's exports. However, make sure we generate
21852197
// anything they depend on first.

tool/input_sdk/private/utils.dart

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,15 @@ import 'dart:_foreign_helper' show JS;
1010
/// by the Dart runtime.
1111
// TODO(ochafik): Rewrite some of these in Dart when possible.
1212

13-
// TODO(ochafik): Make these final + special-case them in js_codegen to fix
14-
// Analyzer errors.
15-
const defineProperty = JS('', 'Object.defineProperty');
16-
const getOwnPropertyDescriptor = JS('', 'Object.getOwnPropertyDescriptor');
17-
const getOwnPropertyNames = JS('', 'Object.getOwnPropertyNames');
18-
const getOwnPropertySymbols = JS('', 'Object.getOwnPropertySymbols');
13+
final defineProperty = JS('', 'Object.defineProperty');
14+
final getOwnPropertyDescriptor = JS('', 'Object.getOwnPropertyDescriptor');
15+
final getOwnPropertyNames = JS('', 'Object.getOwnPropertyNames');
16+
final getOwnPropertySymbols = JS('', 'Object.getOwnPropertySymbols');
1917

20-
const hasOwnProperty = JS('', 'Object.prototype.hasOwnProperty');
18+
final hasOwnProperty = JS('', 'Object.prototype.hasOwnProperty');
2119

2220
// TODO(ochafik): Add ES6 class syntax support to JS intrinsics to avoid this.
23-
const StrongModeError = JS('', '''(function() {
21+
final StrongModeError = JS('', '''(function() {
2422
function StrongModeError(message) {
2523
Error.call(this);
2624
this.message = message;

tool/sdk_expected_errors.txt

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,6 @@
11
severe: [AnalyzerMessage] The redirected constructor '(dynamic) → JSArray<dynamic>' has incompatible parameters with '(dynamic) → JSArray<E>' (dart:_interceptors/js_array.dart, line 29, col 46)
22
severe: [AnalyzerMessage] Missing concrete implementation of 'num.==' (dart:_interceptors/js_number.dart, line 12, col 7)
33
severe: [AnalyzerMessage] Missing concrete implementation of 'String.==' (dart:_interceptors/js_string.dart, line 14, col 7)
4-
severe: [AnalyzerMessage] 'const' variables must be constant value (dart:_utils, line 15, col 24)
5-
severe: [AnalyzerMessage] 'const' variables must be constant value (dart:_utils, line 16, col 34)
6-
severe: [AnalyzerMessage] 'const' variables must be constant value (dart:_utils, line 17, col 29)
7-
severe: [AnalyzerMessage] 'const' variables must be constant value (dart:_utils, line 18, col 31)
8-
severe: [AnalyzerMessage] 'const' variables must be constant value (dart:_utils, line 20, col 24)
9-
severe: [AnalyzerMessage] 'const' variables must be constant value (dart:_utils, line 23, col 25)
104
severe: [AnalyzerMessage] The redirected constructor '((Stream<dynamic>, bool) → StreamSubscription<dynamic>) → _StreamSubscriptionTransformer<dynamic, dynamic>' has incompatible parameters with '((Stream<S>, bool) → StreamSubscription<T>) → StreamTransformer<S, T>' (dart:async/stream.dart, line 1571, col 9)
115
severe: [AnalyzerMessage] The redirected constructor '({handleData: (dynamic, EventSink<dynamic>) → void, handleError: (Object, StackTrace, EventSink<dynamic>) → void, handleDone: (EventSink<dynamic>) → void}) → _StreamHandlerTransformer<dynamic, dynamic>' has incompatible parameters with '({handleData: (S, EventSink<T>) → void, handleError: (Object, StackTrace, EventSink<T>) → void, handleDone: (EventSink<T>) → void}) → StreamTransformer<S, T>' (dart:async/stream.dart, line 1588, col 13)
126
severe: [AnalyzerMessage] The type '_NoCallbackSyncStreamController' is declared with 0 type parameters, but 1 type arguments were given (dart:async/stream_controller.dart, line 84, col 17)

0 commit comments

Comments
 (0)