[dart2js] Cache globalThis

Feature-test for `self` and `globalThis`, and cache the result.

The cached access has smaller minified code size than either `self` or `globalThis`.

All older browsers that we have supported that don't have `globalThis`
do have `self`.

We prioritize `self` over `globalThis`. They are usually the same but it is possible that there are programs which run in an environment that has replaced `self`, for example, a test might do that. We don't want to break existing tests.

Bug: #59982
Change-Id: I11d19183d85a73e9552b66a2f49ac99be10c3c83
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/417912
Reviewed-by: Srujan Gaddam <srujzs@google.com>
Commit-Queue: Stephen Adams <sra@google.com>
This commit is contained in:
Stephen Adams
2025-03-27 15:33:43 -07:00
committed by Commit Queue
parent 82420ba66c
commit 2d21ca796a
7 changed files with 39 additions and 4 deletions
@@ -2011,6 +2011,12 @@ class FragmentEmitter {
) {
List<js.Property> globals = [];
globals.add(
js.Property(
js.string(CACHED_GLOBAL_THIS),
js.js(r'typeof self != "undefined" ? self : globalThis'),
),
);
if (fragmentsToLoad.isNotEmpty) {
globals.addAll(
emitEmbeddedGlobalsForDeferredLoading(
@@ -10,6 +10,7 @@ import 'package:js_runtime/synced/array_flags.dart' show ArrayFlags;
import 'package:js_runtime/synced/embedded_names.dart'
show
CACHED_GLOBAL_THIS,
DEFERRED_INITIALIZED,
DEFERRED_LIBRARY_PARTS,
DEFERRED_PART_URIS,
+6 -1
View File
@@ -654,6 +654,10 @@ class NativeBehavior {
behavior.sideEffects.setTo(newEffects);
}
void setUseGvn(bool useGvn) {
behavior.useGvn = useGvn;
}
processSpecString(
commonElements.dartTypes,
reporter,
@@ -662,6 +666,7 @@ class NativeBehavior {
validTags: validTags,
lookupType: lookupType,
setSideEffects: setSideEffects,
setUseGvn: setUseGvn,
typesReturned: behavior.typesReturned,
typesInstantiated: behavior.typesInstantiated,
objectType: commonElements.objectType,
@@ -709,7 +714,7 @@ class NativeBehavior {
lookupType,
reporter,
commonElements,
validTags: ['returns', 'creates'],
validTags: ['returns', 'creates', 'depends', 'effects', 'gvn'],
);
return behavior;
}
+7 -2
View File
@@ -2723,8 +2723,13 @@ class HForeignCode extends HForeign {
bool typeEquals(other) => other is HForeignCode;
@override
bool dataEquals(HForeignCode other) {
return codeTemplate.source != null &&
codeTemplate.source == other.codeTemplate.source;
if (codeTemplate.source == null) {
return other.codeTemplate.source == null &&
// The ASTs will be equal if identical, and in some limited other
// cases, like a ModularExpression.
codeTemplate.ast == other.codeTemplate.ast;
}
return codeTemplate.source == other.codeTemplate.source;
}
@override
@@ -183,6 +183,10 @@ const STARTUP_METRICS = 'sm';
// TODO(51016): This might be moved to improve deferred loading.
const RECORD_TYPE_TEST_COMBINATORS_PROPERTY = 'rttc';
/// An embedded global that contains the value of `globalThis`. Unlike many
/// embedded globals, this one has many references, so we choose short name.
const CACHED_GLOBAL_THIS = 'G';
/// Names of fields of collected tear-off parameters object.
///
/// Tear-off getters are created before the Dart classes are initialized, so a
@@ -6,6 +6,7 @@ library _js_helper;
import 'dart:_js_embedded_names'
show
CACHED_GLOBAL_THIS,
CURRENT_SCRIPT,
DEFERRED_LIBRARY_PARTS,
DEFERRED_PART_URIS,
@@ -3953,8 +3954,17 @@ abstract class TrustedGetRuntimeType {}
/// `pkg/_js_interop_checks/lib/src/js_util_optimizer.dart`.
///
/// This should match the global context that non-static interop members use.
@pragma('dart2js:prefer-inline')
// Unlike `JS<T>(...)`, `JS_EMBEDDED_GLOBAL` is not generic. So we need to cast
// the dynamic result to the desired type. We know the result is some kind of
// non-null, non-Dart object.
@pragma('dart2js:as:trust')
Object get staticInteropGlobalContext =>
JS('creates:;returns:Object;depends:none;effects:none;gvn:true', 'self');
JS_EMBEDDED_GLOBAL(
'creates:;returns:JSObject;depends:none;effects:none;gvn:true',
CACHED_GLOBAL_THIS,
)
as Object;
/// Return a fresh object literal.
T createObjectLiteral<T>() => JS('PlainJavaScriptObject', '{}');
@@ -183,6 +183,10 @@ const STARTUP_METRICS = 'sm';
// TODO(51016): This might be moved to improve deferred loading.
const RECORD_TYPE_TEST_COMBINATORS_PROPERTY = 'rttc';
/// An embedded global that contains the value of `globalThis`. Unlike many
/// embedded globals, this one has many references, so we choose short name.
const CACHED_GLOBAL_THIS = 'G';
/// Names of fields of collected tear-off parameters object.
///
/// Tear-off getters are created before the Dart classes are initialized, so a