Commit 219e7631 authored by yangguo@chromium.org's avatar yangguo@chromium.org

Expose the content of Maps and WeakMaps through MapMirror.

BUG=v8:3291
LOG=N
R=aandrey@chromium.org, yangguo@chromium.org

Committed: https://code.google.com/p/v8/source/detail?r=22452

Review URL: https://codereview.chromium.org/398513005

Patch from Alexandra Mikhaylova <amikhaylova@google.com>.

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22490 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent c18a36fd
......@@ -81,6 +81,8 @@ function MakeMirror(value, opt_transient) {
mirror = new ErrorMirror(value);
} else if (IS_SCRIPT(value)) {
mirror = new ScriptMirror(value);
} else if (IS_MAP(value) || IS_WEAKMAP(value)) {
mirror = new MapMirror(value);
} else if (ObjectIsPromise(value)) {
mirror = new PromiseMirror(value);
} else {
......@@ -155,6 +157,7 @@ var SCRIPT_TYPE = 'script';
var CONTEXT_TYPE = 'context';
var SCOPE_TYPE = 'scope';
var PROMISE_TYPE = 'promise';
var MAP_TYPE = 'map';
// Maximum length when sending strings through the JSON protocol.
var kMaxProtocolStringLength = 80;
......@@ -210,6 +213,7 @@ var ScopeType = { Global: 0,
// - RegExpMirror
// - ErrorMirror
// - PromiseMirror
// - MapMirror
// - PropertyMirror
// - InternalPropertyMirror
// - FrameMirror
......@@ -420,6 +424,15 @@ Mirror.prototype.isScope = function() {
};
/**
* Check whether the mirror reflects a map.
* @returns {boolean} True if the mirror reflects a map
*/
Mirror.prototype.isMap = function() {
return this instanceof MapMirror;
};
/**
* Allocate a handle id for this object.
*/
......@@ -1253,6 +1266,44 @@ PromiseMirror.prototype.promiseValue = function() {
};
function MapMirror(value) {
%_CallFunction(this, value, MAP_TYPE, ObjectMirror);
}
inherits(MapMirror, ObjectMirror);
/**
* Returns an array of key/value pairs of a map.
* This will keep keys alive for WeakMaps.
*
* @returns {Array.<Object>} Array of key/value pairs of a map.
*/
MapMirror.prototype.entries = function() {
var result = [];
if (IS_WEAKMAP(this.value_)) {
var entries = %GetWeakMapEntries(this.value_);
for (var i = 0; i < entries.length; i += 2) {
result.push({
key: entries[i],
value: entries[i + 1]
});
}
return result;
}
var iter = %_CallFunction(this.value_, builtins.MapEntries);
var next;
while (!(next = iter.next()).done) {
result.push({
key: next.value[0],
value: next.value[1]
});
}
return result;
};
/**
* Base mirror object for properties.
* @param {ObjectMirror} mirror The mirror object having this property
......
......@@ -1688,6 +1688,29 @@ RUNTIME_FUNCTION(Runtime_MapIteratorInitialize) {
}
RUNTIME_FUNCTION(Runtime_GetWeakMapEntries) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, holder, 0);
Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
Handle<FixedArray> entries =
isolate->factory()->NewFixedArray(table->NumberOfElements() * 2);
{
DisallowHeapAllocation no_gc;
int number_of_non_hole_elements = 0;
for (int i = 0; i < table->Capacity(); i++) {
Handle<Object> key(table->KeyAt(i), isolate);
if (table->IsKey(*key)) {
entries->set(number_of_non_hole_elements++, *key);
entries->set(number_of_non_hole_elements++, table->Lookup(key));
}
}
ASSERT_EQ(table->NumberOfElements() * 2, number_of_non_hole_elements);
}
return *isolate->factory()->NewJSArrayWithElements(entries);
}
RUNTIME_FUNCTION(Runtime_MapIteratorNext) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 2);
......
......@@ -296,6 +296,8 @@ namespace internal {
F(WeakCollectionDelete, 2, 1) \
F(WeakCollectionSet, 3, 1) \
\
F(GetWeakMapEntries, 1, 1) \
\
/* Harmony events */ \
F(EnqueueMicrotask, 1, 1) \
F(RunMicrotasks, 0, 1) \
......
// 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 --expose-gc --harmony-collections
function testMapMirror(mirror) {
// Create JSON representation.
var serializer = debug.MakeMirrorSerializer();
var json = JSON.stringify(serializer.serializeValue(mirror));
// Check the mirror hierachy.
assertTrue(mirror instanceof debug.Mirror);
assertTrue(mirror instanceof debug.ValueMirror);
assertTrue(mirror instanceof debug.ObjectMirror);
assertTrue(mirror instanceof debug.MapMirror);
assertTrue(mirror.isMap());
// Parse JSON representation and check.
var fromJSON = eval('(' + json + ')');
assertEquals('map', fromJSON.type);
}
var o1 = new Object();
var o2 = new Object();
var o3 = new Object();
// Test the mirror object for Maps
var map = new Map();
map.set(o1, 11);
map.set(o2, 22);
map.delete(o1);
var mapMirror = debug.MakeMirror(map);
testMapMirror(mapMirror);
var entries = mapMirror.entries();
assertEquals(1, entries.length);
assertSame(o2, entries[0].key);
assertEquals(22, entries[0].value);
map.set(o1, 33);
map.set(o3, o2);
map.delete(o2);
map.set(undefined, 44);
entries = mapMirror.entries();
assertEquals(3, entries.length);
assertSame(o1, entries[0].key);
assertEquals(33, entries[0].value);
assertSame(o3, entries[1].key);
assertSame(o2, entries[1].value);
assertEquals(undefined, entries[2].key);
assertEquals(44, entries[2].value);
// Test the mirror object for WeakMaps
var weakMap = new WeakMap();
weakMap.set(o1, 11);
weakMap.set(new Object(), 22);
weakMap.set(o3, 33);
weakMap.set(new Object(), 44);
var weakMapMirror = debug.MakeMirror(weakMap);
testMapMirror(weakMapMirror);
weakMap.set(new Object(), 55);
assertTrue(weakMapMirror.entries().length <= 5);
gc();
function testWeakMapEntries(weakMapMirror) {
var entries = weakMapMirror.entries();
assertEquals(2, entries.length);
var found = 0;
for (var i = 0; i < entries.length; i++) {
if (Object.is(entries[i].key, o1)) {
assertEquals(11, entries[i].value);
found++;
}
if (Object.is(entries[i].key, o3)) {
assertEquals(33, entries[i].value);
found++;
}
}
assertEquals(2, found);
}
testWeakMapEntries(weakMapMirror);
// Copyright 2014 the V8 project authors. All rights reserved.
// AUTO-GENERATED BY tools/generate-runtime-tests.py, DO NOT MODIFY
// Flags: --allow-natives-syntax --harmony
var _holder = new WeakMap();
%GetWeakMapEntries(_holder);
......@@ -47,11 +47,11 @@ EXPAND_MACROS = [
# that the parser doesn't bit-rot. Change the values as needed when you add,
# remove or change runtime functions, but make sure we don't lose our ability
# to parse them!
EXPECTED_FUNCTION_COUNT = 417
EXPECTED_FUZZABLE_COUNT = 332
EXPECTED_FUNCTION_COUNT = 418
EXPECTED_FUZZABLE_COUNT = 333
EXPECTED_CCTEST_COUNT = 8
EXPECTED_UNKNOWN_COUNT = 4
EXPECTED_BUILTINS_COUNT = 809
EXPECTED_BUILTINS_COUNT = 810
# Don't call these at all.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment