}
+// Wrapper to check whether an object is a Promise. The call may not work
+// if promises are not enabled.
+// TODO(yangguo): remove this wrapper once promises are enabled by default.
+function ObjectIsPromise(value) {
+ try {
+ return %IsPromise(value);
+ } catch (e) {
+ return false;
+ }
+}
+
+
/**
* Returns the mirror for a specified value or object.
*
mirror = new ErrorMirror(value);
} else if (IS_SCRIPT(value)) {
mirror = new ScriptMirror(value);
+ } else if (ObjectIsPromise(value)) {
+ mirror = new PromiseMirror(value);
} else {
mirror = new ObjectMirror(value, OBJECT_TYPE, opt_transient);
}
var SCRIPT_TYPE = 'script';
var CONTEXT_TYPE = 'context';
var SCOPE_TYPE = 'scope';
+var PROMISE_TYPE = 'promise';
// Maximum length when sending strings through the JSON protocol.
var kMaxProtocolStringLength = 80;
// - DateMirror
// - RegExpMirror
// - ErrorMirror
+// - PromiseMirror
// - PropertyMirror
// - InternalPropertyMirror
// - FrameMirror
/**
+ * Check whether the mirror reflects a promise.
+ * @returns {boolean} True if the mirror reflects a promise
+ */
+Mirror.prototype.isPromise = function() {
+ return this instanceof PromiseMirror;
+};
+
+
+/**
* Check whether the mirror reflects a property.
* @returns {boolean} True if the mirror reflects a property
*/
// Find all the named properties.
if (kind & PropertyKind.Named) {
- // Get all the local property names.
+ // Get all the local property names except for private symbols.
propertyNames =
- %GetLocalPropertyNames(this.value_, PROPERTY_ATTRIBUTES_NONE);
+ %GetLocalPropertyNames(this.value_, PROPERTY_ATTRIBUTES_PRIVATE_SYMBOL);
total += propertyNames.length;
// Get names for named interceptor properties if any.
/**
+ * Mirror object for a Promise object.
+ * @param {Object} data The Promise object
+ * @constructor
+ * @extends Mirror
+ */
+function PromiseMirror(value) {
+ %_CallFunction(this, value, PROMISE_TYPE, ObjectMirror);
+}
+inherits(PromiseMirror, ObjectMirror);
+
+
+PromiseMirror.prototype.status = function() {
+ var status = %GetPromiseStatus(this.value_);
+ if (status == 0) return "pending";
+ if (status == 1) return "resolved";
+ return "rejected";
+};
+
+
+/**
* Base mirror object for properties.
* @param {ObjectMirror} mirror The mirror object having this property
* @param {string} name The name of the property
case FUNCTION_TYPE:
case ERROR_TYPE:
case REGEXP_TYPE:
+ case PROMISE_TYPE:
// Add object representation.
this.serializeObject_(mirror, content, details);
break;
content.indexedInterceptor = true;
}
- // Add function specific properties.
if (mirror.isFunction()) {
// Add function specific properties.
content.name = mirror.name();
}
}
- // Add date specific properties.
if (mirror.isDate()) {
// Add date specific properties.
content.value = mirror.value();
}
+ if (mirror.isPromise()) {
+ // Add promise specific properties.
+ content.status = mirror.status();
+ }
+
// Add actual properties - named properties followed by indexed properties.
var propertyNames = mirror.propertyNames(PropertyKind.Named);
var propertyIndexes = mirror.propertyNames(PropertyKind.Indexed);
--- /dev/null
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug --harmony-promises
+// Test the mirror object for promises.
+
+function MirrorRefCache(json_refs) {
+ var tmp = eval('(' + json_refs + ')');
+ this.refs_ = [];
+ for (var i = 0; i < tmp.length; i++) {
+ this.refs_[tmp[i].handle] = tmp[i];
+ }
+}
+
+MirrorRefCache.prototype.lookup = function(handle) {
+ return this.refs_[handle];
+}
+
+function testPromiseMirror(promise, status) {
+ // Create mirror and JSON representation.
+ var mirror = debug.MakeMirror(promise);
+ var serializer = debug.MakeMirrorSerializer();
+ var json = JSON.stringify(serializer.serializeValue(mirror));
+ var refs = new MirrorRefCache(
+ JSON.stringify(serializer.serializeReferencedObjects()));
+
+ // Check the mirror hierachy.
+ assertTrue(mirror instanceof debug.Mirror);
+ assertTrue(mirror instanceof debug.ValueMirror);
+ assertTrue(mirror instanceof debug.ObjectMirror);
+ assertTrue(mirror instanceof debug.PromiseMirror);
+
+ // Check the mirror properties.
+ assertEquals(status, mirror.status());
+ assertTrue(mirror.isPromise());
+ assertEquals('promise', mirror.type());
+ assertFalse(mirror.isPrimitive());
+ assertEquals("Object", mirror.className());
+ assertEquals("#<Promise>", mirror.toText());
+ assertSame(promise, mirror.value());
+
+ // Parse JSON representation and check.
+ var fromJSON = eval('(' + json + ')');
+ assertEquals('promise', fromJSON.type);
+ assertEquals('Object', fromJSON.className);
+ assertEquals('function', refs.lookup(fromJSON.constructorFunction.ref).type);
+ assertEquals('Promise', refs.lookup(fromJSON.constructorFunction.ref).name);
+ assertEquals(status, fromJSON.status);
+
+}
+
+// Test a number of different promises.
+var resolved = new Promise(function(resolve, reject) { resolve() });
+var rejected = new Promise(function(resolve, reject) { reject() });
+var pending = new Promise(function(resolve, reject) {});
+
+testPromiseMirror(resolved, "resolved");
+testPromiseMirror(rejected, "rejected");
+testPromiseMirror(pending, "pending");