Index: tool/input_sdk/private/utils.dart |
diff --git a/tool/input_sdk/private/utils.dart b/tool/input_sdk/private/utils.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c4a81ea14de214abd707b0d1245558fa5624627d |
--- /dev/null |
+++ b/tool/input_sdk/private/utils.dart |
@@ -0,0 +1,123 @@ |
+// 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. |
+ |
+library dart._utils; |
+ |
+import 'dart:_foreign_helper' show JS; |
+ |
+/// 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. |
+ |
+// TODO(ochafik): Make these final + special-case them in js_codegen to fix |
+// Analyzer errors. |
+const defineProperty = JS('', 'Object.defineProperty'); |
+const getOwnPropertyDescriptor = JS('', 'Object.getOwnPropertyDescriptor'); |
+const getOwnPropertyNames = JS('', 'Object.getOwnPropertyNames'); |
+const getOwnPropertySymbols = JS('', 'Object.getOwnPropertySymbols'); |
+ |
+const hasOwnProperty = JS('', 'Object.prototype.hasOwnProperty'); |
+ |
+// TODO(ochafik): Add ES6 class syntax support to JS intrinsics to avoid this. |
+const StrongModeError = JS('', '''(function() { |
+ function StrongModeError(message) { |
+ Error.call(this); |
+ this.message = message; |
+ }; |
+ Object.setPrototypeOf(StrongModeError.prototype, Error.prototype); |
+ return StrongModeError; |
+})()'''); |
+ |
+/// This error indicates a strong mode specific failure. |
+void throwStrongModeError(String message) => JS('', '''((message) => { |
+ throw new StrongModeError(message); |
+})(#)''', message); |
+ |
+/// This error indicates a bug in the runtime or the compiler. |
+void throwInternalError(String message) => JS('', '''((message) => { |
+ throw Error(message); |
+})(#)''', message); |
+ |
+// TODO(ochafik): Re-introduce a @JS annotation in the SDK (same as package:js) |
+// so that this is named 'assert' in JavaScript. |
+void assert_(bool condition) => JS('', '''((condition) => { |
+ if (!condition) throwInternalError("The compiler is broken: failed assert"); |
+})(#)''', condition); |
+ |
+getOwnNamesAndSymbols(obj) => JS('', '''((obj) => { |
+ return getOwnPropertyNames(obj).concat(getOwnPropertySymbols(obj)); |
+})(#)''', obj); |
+ |
+safeGetOwnProperty(obj, String name) => JS('', '''((obj, name) => { |
+ let desc = getOwnPropertyDescriptor(obj, name); |
+ if (desc) return desc.value; |
+})(#, #)''', obj, name); |
+ |
+/// Defines a lazy property. |
+/// After initial get or set, it will replace itself with a value property. |
+// TODO(jmesserly): reusing descriptor objects has been shown to improve |
+// performance in other projects (e.g. webcomponents.js ShadowDOM polyfill). |
+defineLazyProperty(to, name, desc) => JS('', '''((to, name, desc) => { |
+ let init = desc.get; |
+ let value = null; |
+ |
+ function lazySetter(x) { |
+ init = null; |
+ value = x; |
+ } |
+ function circularInitError() { |
+ throwInternalError('circular initialization for field ' + name); |
+ } |
+ function lazyGetter() { |
+ if (init == null) return value; |
+ |
+ // Compute and store the value, guarding against reentry. |
+ let f = init; |
+ init = circularInitError; |
+ lazySetter(f()); |
+ return value; |
+ } |
+ desc.get = lazyGetter; |
+ desc.configurable = true; |
+ if (desc.set) desc.set = lazySetter; |
+ return defineProperty(to, name, desc); |
+})(#, #, #)''', to, name, desc); |
+ |
+void defineLazy(to, from) => JS('', '''((to, from) => { |
+ for (let name of getOwnNamesAndSymbols(from)) { |
+ defineLazyProperty(to, name, getOwnPropertyDescriptor(from, name)); |
+ } |
+})(#, #)''', to, from); |
+ |
+defineMemoizedGetter(obj, String name, getter) => |
+ JS('', '''((obj, name, getter) => { |
+ return defineLazyProperty(obj, name, {get: getter}); |
+})(#, #, #)''', obj, name, getter); |
+ |
+copyTheseProperties(to, from, names) => JS('', '''((to, from, names) => { |
+ for (let name of names) { |
+ defineProperty(to, name, getOwnPropertyDescriptor(from, name)); |
+ } |
+ return to; |
+})(#, #, #)''', to, from, names); |
+ |
+/// Copy properties from source to destination object. |
+/// This operation is commonly called `mixin` in JS. |
+copyProperties(to, from) => JS('', '''((to, from) => { |
+ return copyTheseProperties(to, from, getOwnNamesAndSymbols(from)); |
+})(#, #)''', to, from); |
+ |
+/// Exports from one Dart module to another. |
+// TODO(ochafik): Re-introduce a @JS annotation in the SDK (same as package:js) |
+// so that this is named 'export' in JavaScript. |
+export_(to, from, show, hide) => JS('', '''((to, from, show, hide) => { |
+ if (show == void 0) { |
+ show = getOwnNamesAndSymbols(from); |
+ } |
+ if (hide != void 0) { |
+ var hideMap = new Set(hide); |
+ show = show.filter((k) => !hideMap.has(k)); |
+ } |
+ return copyTheseProperties(to, from, show); |
+})(#, #, #, #)''', to, from, show, hide); |