blob: b933c8f2596eb679f28188a8dd2173531c2b7cbb [file] [log] [blame]
// 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.
part of dart._runtime;
/// This library defines a set of general javascript utilities for us
/// by the Dart runtime.
// TODO(ochafik): Rewrite some of these in Dart when possible.
final Function(dynamic, dynamic, dynamic) defineProperty =
JS('', 'Object.defineProperty');
defineValue(obj, name, value) {
defineAccessor(obj, name, value: value, configurable: true, writable: true);
return value;
}
final Function(dynamic, dynamic,
{dynamic get,
dynamic set,
dynamic value,
bool? configurable,
bool? writable}) defineAccessor = JS('', 'Object.defineProperty');
final dynamic Function(dynamic, dynamic) getOwnPropertyDescriptor =
JS('', 'Object.getOwnPropertyDescriptor');
final List Function(dynamic) getOwnPropertyNames =
JS('', 'Object.getOwnPropertyNames');
final List Function(dynamic) getOwnPropertySymbols =
JS('', 'Object.getOwnPropertySymbols');
final Function(dynamic) getPrototypeOf = JS('', 'Object.getPrototypeOf');
/// This error indicates a strong mode specific failure, other than a type
/// assertion failure (TypeError) or CastError.
void throwTypeError(String message) {
throw TypeErrorImpl(message);
}
/// This error indicates a bug in the runtime or the compiler.
void throwInternalError(String message) {
JS('', 'throw Error(#)', message);
}
Iterable getOwnNamesAndSymbols(obj) {
var names = getOwnPropertyNames(obj);
var symbols = getOwnPropertySymbols(obj);
return JS('', '#.concat(#)', names, symbols);
}
/// Returns the value of field `name` on `obj`.
///
/// We use this instead of obj[name] since obj[name] checks the entire
/// prototype chain instead of just `obj`.
safeGetOwnProperty(obj, name) {
if (JS<bool>('!', '#.hasOwnProperty(#)', obj, name))
return JS<Object>('', '#[#]', obj, name);
}
copyTheseProperties(to, from, names) {
for (int i = 0, n = JS('!', '#.length', names); i < n; ++i) {
var name = JS('', '#[#]', names, i);
if (name == 'constructor') continue;
copyProperty(to, from, name);
}
return to;
}
copyProperty(to, from, name) {
var desc = getOwnPropertyDescriptor(from, name);
if (JS('!', '# == Symbol.iterator', name)) {
// On native types, Symbol.iterator may already be present.
// TODO(jmesserly): investigate if we still need this.
// If so, we need to find a better solution.
// See https://github.com/dart-lang/sdk/issues/28324
var existing = getOwnPropertyDescriptor(to, name);
if (existing != null) {
if (JS('!', '#.writable', existing)) {
JS('', '#[#] = #.value', to, name, desc);
}
return;
}
}
defineProperty(to, name, desc);
}
@JSExportName('export')
exportProperty(to, from, name) => copyProperty(to, from, name);
/// Copy properties from source to destination object.
/// This operation is commonly called `mixin` in JS.
copyProperties(to, from) {
return copyTheseProperties(to, from, getOwnNamesAndSymbols(from));
}