Index: lib/runtime/dart_runtime.js |
diff --git a/lib/runtime/dart_runtime.js b/lib/runtime/dart_runtime.js |
index e80d4131cb47fdc4875ba813d3ce4138913a2326..ee1f5129a37bfa0ab5faf305eace44f65e88fde3 100644 |
--- a/lib/runtime/dart_runtime.js |
+++ b/lib/runtime/dart_runtime.js |
@@ -597,6 +597,43 @@ var dart, _js_helper; |
} |
dart.copyProperties = copyProperties; |
+ /** |
+ * Initialize field `name` on `obj` to `value`. |
+ * |
+ * We may have getters/setters in our prototype chain, so we can't simply set |
+ * `obj.name = value` in all cases. |
+ */ |
+ function initField(type, obj, name, value) { |
+ var prop = getOwnPropertyDescriptor(type.prototype, name); |
+ if (prop) { |
+ prop.set.call(obj, value); |
+ } else { |
+ obj[name] = value; |
+ } |
+ } |
+ dart.initField = initField; |
+ |
+ /** |
+ * This is called whenever a derived class needs to introduce a new field, |
+ * shadowing a field or getter/setter pair on its parent. |
+ * |
+ * This is important because otherwise, trying to read or write the field |
+ * would end up calling the getter or setter, and one of those might not even |
+ * exist, resulting in a runtime error. Even if they did exist, that's the |
+ * wrong behavior if a new field was declared. |
+ */ |
+ function virtualField(subclass, fieldName) { |
+ // If the field is already overridden, do nothing. |
+ let prop = getOwnPropertyDescriptor(subclass.prototype, fieldName); |
+ if (prop) return; |
+ |
+ let symbol = Symbol(subclass.name + '.' + fieldName); |
+ defineProperty(subclass.prototype, fieldName, { |
+ get: function() { return this[symbol]; }, |
+ set: function(x) { this[symbol] = x; } |
+ }); |
+ } |
+ dart.virtualField = virtualField; |
/** The Symbol for storing type arguments on a specialized generic type. */ |
dart.mixins = Symbol('mixins'); |