Index: lib/runtime/js_utils.js |
diff --git a/lib/runtime/js_utils.js b/lib/runtime/js_utils.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..a7d6c9d46514d3a393405f6874380c5ac9cbbd9f |
--- /dev/null |
+++ b/lib/runtime/js_utils.js |
@@ -0,0 +1,116 @@ |
+// 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. |
+ |
+/* This library defines a set of general javascript utilities for us |
Jennifer Messerly
2015/06/12 20:12:49
btw, I just noticed this library could be more tig
|
+ * by the Dart runtime. |
+*/ |
+ |
+var js_utils; |
+(function (js_utils) { |
+ 'use strict'; |
+ |
+ const defineProperty = Object.defineProperty; |
+ js_utils.defineProperty = defineProperty; |
Jennifer Messerly
2015/06/12 17:32:25
hmm, not sure this is worth it. We can get all of
Leaf
2015/06/12 19:52:14
I was having a hard time remembering which of the
Jennifer Messerly
2015/06/12 20:12:49
yeah I don't feel super strongly. Seems like it's
Leaf
2015/06/12 20:34:25
My problem was in remembering where to import them
|
+ const getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; |
+ js_utils.getOwnPropertyDescriptor = getOwnPropertyDescriptor; |
+ const getOwnPropertyNames = Object.getOwnPropertyNames; |
+ js_utils.getOwnPropertyNames = getOwnPropertyNames; |
+ const getOwnPropertySymbols = Object.getOwnPropertySymbols; |
+ js_utils.getOwnPropertySymbols = getOwnPropertySymbols; |
+ const hasOwnProperty = Object.prototype.hasOwnProperty; |
+ js_utils.hasOwnProperty = hasOwnProperty; |
+ const slice = [].slice; |
+ js_utils.slice = [].slice; |
+ |
+ /* This error indicates a bug in the runtime or the compiler. |
Jennifer Messerly
2015/06/12 20:12:49
/** ?
Leaf
2015/06/12 20:34:25
Already fixed in last update.
|
+ */ |
+ function throwRuntimeError(message) { |
+ throw Error(message); |
+ } |
+ js_utils.throwRuntimeError = throwRuntimeError; |
+ |
+ function assert(condition) { |
+ if (!condition) throwRuntimeError("The compiler is broken: failed assert"); |
+ } |
+ js_utils.assert = assert; |
+ |
+ function getOwnNamesAndSymbols(obj) { |
+ return getOwnPropertyNames(obj).concat(getOwnPropertySymbols(obj)); |
+ } |
+ js_utils.getOwnNamesAndSymbols = getOwnNamesAndSymbols; |
+ |
+ function safeGetOwnProperty(obj, name) { |
+ let desc = getOwnPropertyDescriptor(obj, name); |
+ if (desc) return desc.value; |
+ } |
+ js_utils.safeGetOwnProperty = safeGetOwnProperty; |
+ |
+ /** |
+ * Defines a lazy property. |
+ * After initial get or set, it will replace itself with a value property. |
+ */ |
+ // TODO(jmesserly): is this the best implementation for JS engines? |
+ // TODO(jmesserly): reusing descriptor objects has been shown to improve |
+ // performance in other projects (e.g. webcomponents.js ShadowDOM polyfill). |
+ function defineLazyProperty(to, name, desc) { |
+ let init = desc.get; |
+ let writable = !!desc.set; |
+ function lazySetter(value) { |
+ defineProperty(to, name, { value: value, writable: writable }); |
+ } |
+ function lazyGetter() { |
+ // Clear the init function to detect circular initialization. |
+ let f = init; |
+ if (f === null) throwRuntimeError('circular initialization for field ' + name); |
Jennifer Messerly
2015/06/12 17:32:25
long line
Leaf
2015/06/12 19:52:14
Done.
|
+ init = null; |
+ |
+ // Compute and store the value. |
+ let value = f(); |
+ lazySetter(value); |
+ return value; |
+ } |
+ desc.get = lazyGetter; |
+ desc.configurable = true; |
+ if (writable) desc.set = lazySetter; |
+ defineProperty(to, name, desc); |
+ } |
+ js_utils.defineLazyProperty = defineLazyProperty; |
+ |
+ function defineLazy(to, from) { |
+ for (let name of getOwnNamesAndSymbols(from)) { |
+ defineLazyProperty(to, name, getOwnPropertyDescriptor(from, name)); |
+ } |
+ } |
+ js_utils.defineLazy = defineLazy; |
+ |
+ function defineMemoizedGetter(obj, name, get) { |
+ let cache = null; |
+ function getter() { |
+ if (cache != null) return cache; |
+ cache = get(); |
+ get = null; |
+ return cache; |
+ } |
+ defineProperty(obj, name, {get: getter, configurable: true}); |
+ } |
+ js_utils.defineMemoizedGetter = defineMemoizedGetter; |
+ |
+ function copyTheseProperties(to, from, names) { |
+ for (let name of names) { |
+ defineProperty(to, name, getOwnPropertyDescriptor(from, name)); |
+ } |
+ return to; |
+ } |
+ js_utils.copyTheseProperties = copyTheseProperties; |
+ |
+ /** |
+ * Copy properties from source to destination object. |
+ * This operation is commonly called `mixin` in JS. |
+ */ |
+ function copyProperties(to, from) { |
+ return copyTheseProperties(to, from, getOwnNamesAndSymbols(from)); |
+ } |
+ js_utils.copyProperties = copyProperties; |
+ |
+})(js_utils || (js_utils = {})); |