}
#if !defined(V8_SHARED)
} else {
+ v8::TryCatch try_catch;
Context::Scope context_scope(utility_context_);
Handle<Object> global = utility_context_->Global();
Handle<Value> fun = global->Get(String::New("Stringify"));
Handle<Value> argv[1] = { result };
Handle<Value> s = Handle<Function>::Cast(fun)->Call(global, 1, argv);
+ if (try_catch.HasCaught()) return true;
v8::String::Utf8Value str(s);
fwrite(*str, sizeof(**str), str.length(), stdout);
printf("\n");
// Find all the named properties.
if (kind & PropertyKind.Named) {
// Get the local property names.
- propertyNames = %GetLocalPropertyNames(this.value_);
+ propertyNames = %GetLocalPropertyNames(this.value_, true);
total += propertyNames.length;
// Get names for named interceptor properties if any.
}
function EnqueueChangeRecord(changeRecord, observers) {
+ // TODO(rossberg): adjust once there is a story for symbols vs proxies.
+ if (IS_SYMBOL(changeRecord.name)) return;
+
for (var i = 0; i < observers.length; i++) {
var observer = observers[i];
var observerInfo = observerInfoMap.get(observer);
Handle<Object> receiver(receiver_raw, isolate);
Handle<Object> name(name_raw, isolate);
+ // TODO(rossberg): adjust once there is a story for symbols vs proxies.
+ if (name->IsSymbol()) return isolate->heap()->undefined_value();
+
Handle<Object> args[] = { receiver, name };
Handle<Object> result = CallTrap(
"get", isolate->derived_get_trap(), ARRAY_SIZE(args), args);
Handle<Object> receiver(this, isolate);
Handle<Object> name(name_raw, isolate);
+ // TODO(rossberg): adjust once there is a story for symbols vs proxies.
+ if (name->IsSymbol()) return false;
+
Handle<Object> args[] = { name };
Handle<Object> result = CallTrap(
"has", isolate->derived_has_trap(), ARRAY_SIZE(args), args);
Handle<Object> name(name_raw, isolate);
Handle<Object> value(value_raw, isolate);
+ // TODO(rossberg): adjust once there is a story for symbols vs proxies.
+ if (name->IsSymbol()) return *value;
+
Handle<Object> args[] = { receiver, name, value };
CallTrap("set", isolate->derived_set_trap(), ARRAY_SIZE(args), args);
if (isolate->has_pending_exception()) return Failure::Exception();
Handle<Object> value(value_raw, isolate);
Handle<Object> handler(this->handler(), isolate); // Trap might morph proxy.
+ // TODO(rossberg): adjust once there is a story for symbols vs proxies.
+ if (name->IsSymbol()) {
+ *done = false;
+ return isolate->heap()->the_hole_value();
+ }
+
*done = true; // except where redefined...
Handle<Object> args[] = { name };
Handle<Object> result = proxy->CallTrap(
if (result->IsUndefined()) {
*done = false;
- return GetHeap()->the_hole_value();
+ return isolate->heap()->the_hole_value();
}
// Emulate [[GetProperty]] semantics for proxies.
Handle<JSProxy> receiver(this);
Handle<Object> name(name_raw, isolate);
+ // TODO(rossberg): adjust once there is a story for symbols vs proxies.
+ if (name->IsSymbol()) return isolate->heap()->false_value();
+
Handle<Object> args[] = { name };
Handle<Object> result = CallTrap(
"delete", Handle<Object>(), ARRAY_SIZE(args), args);
Handle<JSReceiver> receiver(receiver_raw);
Handle<Object> name(name_raw, isolate);
+ // TODO(rossberg): adjust once there is a story for symbols vs proxies.
+ if (name->IsSymbol()) return ABSENT;
+
Handle<Object> args[] = { name };
Handle<Object> result = CallTrap(
"getPropertyDescriptor", Handle<Object>(), ARRAY_SIZE(args), args);
// Fill in the names of local properties into the supplied storage. The main
// purpose of this function is to provide reflection information for the object
// mirrors.
-void JSObject::GetLocalPropertyNames(FixedArray* storage, int index) {
- ASSERT(storage->length() >= (NumberOfLocalProperties() - index));
+void JSObject::GetLocalPropertyNames(
+ FixedArray* storage, int index, PropertyAttributes filter) {
+ ASSERT(storage->length() >= (NumberOfLocalProperties(filter) - index));
if (HasFastProperties()) {
int real_size = map()->NumberOfOwnDescriptors();
DescriptorArray* descs = map()->instance_descriptors();
- ASSERT(storage->length() >= index + real_size);
for (int i = 0; i < real_size; i++) {
- storage->set(index + i, descs->GetKey(i));
+ if ((descs->GetDetails(i).attributes() & filter) == 0 &&
+ ((filter & SYMBOLIC) == 0 || !descs->GetKey(i)->IsSymbol())) {
+ storage->set(index++, descs->GetKey(i));
+ }
}
} else {
property_dictionary()->CopyKeysTo(storage,
index,
+ filter,
NameDictionary::UNSORTED);
}
}
template void Dictionary<NameDictionaryShape, Name*>::CopyKeysTo(
FixedArray*,
int,
+ PropertyAttributes,
Dictionary<NameDictionaryShape, Name*>::SortMode);
template int
void Dictionary<Shape, Key>::CopyKeysTo(
FixedArray* storage,
int index,
+ PropertyAttributes filter,
typename Dictionary<Shape, Key>::SortMode sort_mode) {
ASSERT(storage->length() >= NumberOfElementsFilterAttributes(
static_cast<PropertyAttributes>(NONE)));
if (HashTable<Shape, Key>::IsKey(k)) {
PropertyDetails details = DetailsAt(i);
if (details.IsDeleted()) continue;
- storage->set(index++, k);
+ PropertyAttributes attr = details.attributes();
+ if ((attr & filter) == 0) storage->set(index++, k);
}
}
if (sort_mode == Dictionary<Shape, Key>::SORTED) {
int NumberOfLocalProperties(PropertyAttributes filter = NONE);
// Fill in details for properties into storage starting at the specified
// index.
- void GetLocalPropertyNames(FixedArray* storage, int index);
+ void GetLocalPropertyNames(
+ FixedArray* storage, int index, PropertyAttributes filter = NONE);
// Returns the number of properties on this object filtering out properties
// with the specified attributes (ignoring interceptors).
PropertyAttributes filter,
SortMode sort_mode);
// Fill in details for properties into storage.
- void CopyKeysTo(FixedArray* storage, int index, SortMode sort_mode);
+ void CopyKeysTo(FixedArray* storage,
+ int index,
+ PropertyAttributes filter,
+ SortMode sort_mode);
// Accessors for next enumeration index.
void SetNextEnumerationIndex(int index) {
RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateSymbol) {
- NoHandleAllocation ha(isolate);
+ HandleScope scope(isolate);
ASSERT(args.length() == 1);
- CONVERT_ARG_HANDLE_CHECKED(Object, name, 0);
+ Handle<Object> name(args[0], isolate);
RUNTIME_ASSERT(name->IsString() || name->IsUndefined());
Symbol* symbol;
MaybeObject* maybe = isolate->heap()->AllocateSymbol();
// args[0]: object
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalPropertyNames) {
HandleScope scope(isolate);
- ASSERT(args.length() == 1);
+ ASSERT(args.length() == 2);
if (!args[0]->IsJSObject()) {
return isolate->heap()->undefined_value();
}
CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
+ CONVERT_BOOLEAN_ARG_CHECKED(include_symbols, 1);
+ PropertyAttributes filter = include_symbols ? NONE : SYMBOLIC;
// Skip the global proxy as it has no properties and always delegates to the
// real global object.
return *isolate->factory()->NewJSArray(0);
}
int n;
- n = jsproto->NumberOfLocalProperties();
+ n = jsproto->NumberOfLocalProperties(filter);
local_property_count[i] = n;
total_property_count += n;
if (i < length - 1) {
int proto_with_hidden_properties = 0;
int next_copy_index = 0;
for (int i = 0; i < length; i++) {
- jsproto->GetLocalPropertyNames(*names, next_copy_index);
+ jsproto->GetLocalPropertyNames(*names, next_copy_index, filter);
next_copy_index += local_property_count[i];
if (jsproto->HasHiddenProperties()) {
proto_with_hidden_properties++;
}
}
- // Filter out name of hidden propeties object.
+ // Filter out name of hidden properties object.
if (proto_with_hidden_properties > 0) {
Handle<FixedArray> old_names = names;
names = isolate->factory()->NewFixedArray(
F(IsPropertyEnumerable, 2, 1) \
F(GetPropertyNames, 1, 1) \
F(GetPropertyNamesFast, 1, 1) \
- F(GetLocalPropertyNames, 1, 1) \
+ F(GetLocalPropertyNames, 2, 1) \
F(GetLocalElementNames, 1, 1) \
F(GetInterceptorInfo, 1, 1) \
F(GetNamedInterceptorPropertyNames, 1, 1) \
if (!IS_SYMBOL(symbol)) {
throw MakeTypeError(
'incompatible_method_receiver', ["Symbol.prototype.name", this]);
-
}
return %SymbolName(symbol);
}
// ECMA-262 - 15.2.4.5
function ObjectHasOwnProperty(V) {
if (%IsJSProxy(this)) {
+ // TODO(rossberg): adjust once there is a story for symbols vs proxies.
+ if (IS_SYMBOL(V)) return false;
+
var handler = %GetHandler(this);
return CallTrap1(handler, "hasOwn", DerivedHasOwnTrap, ToName(V));
}
function ObjectPropertyIsEnumerable(V) {
var P = ToName(V);
if (%IsJSProxy(this)) {
+ // TODO(rossberg): adjust once there is a story for symbols vs proxies.
+ if (IS_SYMBOL(V)) return false;
+
var desc = GetOwnProperty(this, P);
return IS_UNDEFINED(desc) ? false : desc.isEnumerable();
}
function GetOwnProperty(obj, v) {
var p = ToName(v);
if (%IsJSProxy(obj)) {
+ // TODO(rossberg): adjust once there is a story for symbols vs proxies.
+ if (IS_SYMBOL(v)) return void 0;
+
var handler = %GetHandler(obj);
var descriptor = CallTrap1(handler, "getOwnPropertyDescriptor", void 0, p);
if (IS_UNDEFINED(descriptor)) return descriptor;
// Harmony proxies.
function DefineProxyProperty(obj, p, attributes, should_throw) {
+ // TODO(rossberg): adjust once there is a story for symbols vs proxies.
+ if (IS_SYMBOL(p)) return false;
+
var handler = %GetHandler(obj);
var result = CallTrap2(handler, "defineProperty", void 0, p, attributes);
if (!ToBoolean(result)) {
// ES5 section 8.12.9, ES5 section 15.4.5.1 and Harmony proxies.
function DefineOwnProperty(obj, p, desc, should_throw) {
if (%IsJSProxy(obj)) {
+ // TODO(rossberg): adjust once there is a story for symbols vs proxies.
+ if (IS_SYMBOL(p)) return false;
+
var attributes = FromGenericPropertyDescriptor(desc);
return DefineProxyProperty(obj, p, attributes, should_throw);
} else if (IS_ARRAY(obj)) {
}
var n = ToUint32(obj.length);
var array = new $Array(n);
+ var realLength = 0;
var names = { __proto__: null }; // TODO(rossberg): use sets once ready.
for (var index = 0; index < n; index++) {
var s = ToName(obj[index]);
+ // TODO(rossberg): adjust once there is a story for symbols vs proxies.
if (IS_SYMBOL(s) && !includeSymbols) continue;
if (%HasLocalProperty(names, s)) {
throw MakeTypeError("proxy_repeated_prop_name", [obj, trap, s]);
}
array[index] = s;
+ ++realLength;
names[s] = 0;
}
+ array.length = realLength;
return array;
}
if (%IsJSProxy(obj)) {
var handler = %GetHandler(obj);
var names = CallTrap0(handler, "getOwnPropertyNames", void 0);
- return ToNameArray(names, "getOwnPropertyNames", true);
+ return ToNameArray(names, "getOwnPropertyNames", false);
}
var nameArrays = new InternalArray();
// Find all the named properties.
// Get the local property names.
- nameArrays.push(%GetLocalPropertyNames(obj));
+ nameArrays.push(%GetLocalPropertyNames(obj, false));
// Get names for named interceptor properties if any.
if ((interceptorInfo & 2) != 0) {
var propertySet = { __proto__: null };
var j = 0;
for (var i = 0; i < propertyNames.length; ++i) {
- var name = ToName(propertyNames[i]);
+ if (IS_SYMBOL(propertyNames[i])) continue;
+ var name = ToString(propertyNames[i]);
// We need to check for the exact property value since for intrinsic
// properties like toString if(propertySet["toString"]) will always
// succeed.
// Call the runtime version of GetLocalPropertyNames() on the natively
// created object through JavaScript.
context->Global()->Set(v8_str("obj"), o4);
- CompileRun("var names = %GetLocalPropertyNames(obj);");
+ CompileRun("var names = %GetLocalPropertyNames(obj, true);");
ExpectInt32("names.length", 1006);
ExpectTrue("names.indexOf(\"baz\") >= 0");
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --harmony-observation --harmony-proxies --harmony-collections
-// Flags: --allow-natives-syntax
+// Flags: --harmony-symbols --allow-natives-syntax
var allObservers = [];
function reset() {
]);
+// Observing symbol properties (not).
+print("*****")
+reset();
+var obj = {}
+var symbol = Symbol("secret");
+Object.observe(obj, observer.callback);
+obj[symbol] = 3;
+delete obj[symbol];
+Object.defineProperty(obj, symbol, {get: function() {}, configurable: true});
+Object.defineProperty(obj, symbol, {value: 6});
+Object.defineProperty(obj, symbol, {writable: false});
+delete obj[symbol];
+Object.defineProperty(obj, symbol, {value: 7});
+++obj[symbol];
+obj[symbol]++;
+obj[symbol] *= 3;
+delete obj[symbol];
+obj.__defineSetter__(symbol, function() {});
+obj.__defineGetter__(symbol, function() {});
+Object.deliverChangeRecords(observer.callback);
+observer.assertNotCalled();
+
+
// Test all kinds of objects generically.
function TestObserveConfigurable(obj, prop) {
reset();
--- /dev/null
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --harmony-proxies --harmony-symbols
+
+
+// Helper.
+
+function TestWithProxies(test, x, y, z) {
+ test(Proxy.create, x, y, z)
+ test(function(h) {return Proxy.createFunction(h, function() {})}, x, y, z)
+}
+
+
+// No symbols should leak to proxy traps.
+
+function TestNoSymbolsToTrap(handler) {
+ TestWithProxies(TestNoSymbolsToTrap2, handler)
+}
+
+function TestNoSymbolsToTrap2(create, handler) {
+ var p = create(handler)
+ var o = Object.create(p)
+ var symbol = Symbol("secret")
+
+ assertFalse(symbol in p)
+ assertFalse(symbol in o)
+ assertEquals(undefined, p[symbol])
+ assertEquals(undefined, o[symbol])
+ assertEquals(47, p[symbol] = 47)
+ assertEquals(47, o[symbol] = 47)
+ assertFalse(delete p[symbol])
+ assertTrue(delete o[symbol])
+ assertTrue(delete o[symbol])
+ assertFalse({}.hasOwnProperty.call(p, symbol))
+ assertFalse({}.hasOwnProperty.call(o, symbol))
+ assertEquals(undefined, Object.getOwnPropertyDescriptor(p, symbol))
+ assertEquals(undefined, Object.getOwnPropertyDescriptor(o, symbol))
+}
+
+
+TestNoSymbolsToTrap({
+ has: assertUnreachable,
+ hasOwn: assertUnreachable,
+ get: assertUnreachable,
+ set: assertUnreachable,
+ delete: assertUnreachable,
+ getPropertyDescriptor: assertUnreachable,
+ getOwnPropertyDescriptor: assertUnreachable,
+ defineProperty: assertUnreachable
+})
+
+
+// All symbols returned from proxy traps should be filtered.
+
+function TestNoSymbolsFromTrap(handler) {
+ TestWithProxies(TestNoSymbolsFromTrap2, handler)
+}
+
+function TestNoSymbolsFromTrap2(create, handler) {
+ var p = create(handler)
+ var o = Object.create(p)
+
+ assertEquals(0, Object.keys(p).length)
+ assertEquals(0, Object.keys(o).length)
+ assertEquals(0, Object.getOwnPropertyNames(p).length)
+ assertEquals(0, Object.getOwnPropertyNames(o).length)
+ for (var n in p) assertUnreachable()
+ for (var n in o) assertUnreachable()
+}
+
+
+function MakeSymbolArray() {
+ return [Symbol(), Symbol("a")]
+}
+
+TestNoSymbolsFromTrap({
+ enumerate: MakeSymbolArray,
+ keys: MakeSymbolArray,
+ getPropertyNames: MakeSymbolArray,
+ getOwnPropertyNames: MakeSymbolArray
+})
function TestKeyEnum(obj) {
for (var name in obj) {
- assertTrue(typeof name !== "symbol")
+ assertEquals("string", typeof name)
}
}
assertEquals(0, Object.keys(obj).length)
var names = Object.getOwnPropertyNames(obj)
- assertTrue(symbols.length <= names.length)
- // TODO(rossberg): once we have iterators, the following would be:
- // var expected = new Set(symbols)
- var expected = new Set
- for (var i = 0; i < symbols.length; ++i) expected.add(symbols[i])
- for (var i = 0; i < names.length; ++i) {
- var name = names[i]
- if (typeof name === 'symbol') {
- assertTrue(expected.has(name))
- expected.delete(name)
- }
+ for (var i in names) {
+ assertEquals("string", typeof names[i])
}
- assertEquals(0, expected.size)
}