Bug 837773 - Add a PropertyKey.h header. r=jorendorff
authorJeff Walden <jwalden@mit.edu>
Fri, 01 Feb 2013 16:42:48 -0800
changeset 120968 43a5c9890c22e54152c997f8800956b517819a3a
parent 120967 06fe741ec9538e7de9fc43a8a730b8d5a1782e78
child 120969 a7f93cfc074e467aa8488de6da01b3ad6d112f4d
push id24269
push useremorley@mozilla.com
push dateWed, 06 Feb 2013 14:27:17 +0000
treeherdermozilla-central@04e13fc9dbff [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs837773
milestone21.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 837773 - Add a PropertyKey.h header. r=jorendorff
js/public/PropertyKey.h
js/public/Value.h
js/src/Makefile.in
js/src/jsapi-tests/testIntTypesABI.cpp
js/src/jsapi.h
js/src/vm/ObjectImpl.cpp
js/src/vm/PropertyKey.cpp
new file mode 100644
--- /dev/null
+++ b/js/public/PropertyKey.h
@@ -0,0 +1,99 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=4 sw=4 et tw=99 ft=cpp:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* JS::PropertyKey implementation. */
+
+#ifndef js_PropertyKey_h___
+#define js_PropertyKey_h___
+
+#include "mozilla/Attributes.h"
+
+#include "js/Value.h"
+
+struct JSContext;
+
+namespace JS {
+
+class PropertyKey;
+
+namespace detail {
+
+extern JS_PUBLIC_API(bool)
+ToPropertyKeySlow(JSContext *cx, HandleValue v, PropertyKey *key);
+
+} // namespace detail
+
+/*
+ * A PropertyKey is a key used to access some property on an object.  It is a
+ * natural way to represent a property accessed using a JavaScript value.
+ *
+ * PropertyKey can represent indexes, named properties, and ES6 symbols.  The
+ * latter aren't implemented in SpiderMonkey yet, but PropertyKey carves out
+ * space for them.
+ */
+class PropertyKey
+{
+    Value v;
+    friend bool detail::ToPropertyKeySlow(JSContext *cx, HandleValue v, PropertyKey *key);
+
+  public:
+    explicit PropertyKey(uint32_t index) : v(PrivateUint32Value(index)) {}
+
+    /*
+     * An index is a string property name whose characters exactly spell out an
+     * unsigned 32-bit integer in decimal: "0", "1", "2", ...., "4294967294",
+     * "4294967295".
+     */
+    bool isIndex(uint32_t *index) {
+        // The implementation here assumes that private uint32_t are stored
+        // using the int32_t representation.  This is purely an implementation
+        // detail: embedders must not rely upon this!
+        if (!v.isInt32())
+            return false;
+        *index = v.toPrivateUint32();
+        return true;
+    }
+
+    /*
+     * A name is a string property name which is *not* an index.  Note that by
+     * the ECMAScript language grammar, any dotted property access |obj.prop|
+     * will access a named property.
+     */
+    bool isName(JSString **str) {
+        uint32_t dummy;
+        if (isIndex(&dummy))
+            return false;
+        *str = v.toString();
+        return true;
+    }
+
+    /*
+     * A symbol is a property name that's a Symbol, a particular kind of object
+     * in ES6.  It is the only kind of property name that's not a string.
+     *
+     * SpiderMonkey doesn't yet implement symbols, but we're carving out API
+     * space for them in advance.
+     */
+    bool isSymbol() {
+        return false;
+    }
+};
+
+inline bool
+ToPropertyKey(JSContext *cx, HandleValue v, PropertyKey *key)
+{
+    if (v.isInt32() && v.toInt32() >= 0) {
+        *key = PropertyKey(uint32_t(v.toInt32()));
+        return true;
+    }
+
+    return detail::ToPropertyKeySlow(cx, v, key);
+}
+
+} // namespace JS
+
+#endif /* js_PropertyKey_h___ */
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -122,16 +122,17 @@ CPPSRCS		= \
 		prmjtime.cpp \
 		sharkctl.cpp \
 		ArgumentsObject.cpp \
 		DateTime.cpp \
 		Debugger.cpp \
 		GlobalObject.cpp \
 		Object.cpp \
 		ObjectImpl.cpp \
+		PropertyKey.cpp \
 		ScopeObject.cpp \
 		Shape.cpp \
 		Stack.cpp \
 		String.cpp \
 		BytecodeCompiler.cpp \
 		BytecodeEmitter.cpp \
 		CharacterEncoding.cpp \
 		FoldConstants.cpp \
@@ -225,16 +226,17 @@ EXPORTS_NAMESPACES += js
 EXPORTS_js = \
 		Anchor.h \
 		CharacterEncoding.h \
 		GCAPI.h \
 		HashTable.h \
 		HeapAPI.h \
 		LegacyIntTypes.h \
 		MemoryMetrics.h \
+		PropertyKey.h \
 		TemplateLib.h \
 		Utility.h \
 		Value.h \
 		Vector.h \
 		$(NULL)
 
 ###############################################
 # BEGIN enable non-releasable features
--- a/js/src/jsapi-tests/testIntTypesABI.cpp
+++ b/js/src/jsapi-tests/testIntTypesABI.cpp
@@ -18,16 +18,17 @@
 #include "jstypes.h"
 
 #include "js/Anchor.h"
 #include "js/CharacterEncoding.h"
 #include "js/GCAPI.h"
 #include "js/HashTable.h"
 #include "js/HeapAPI.h"
 #include "js/MemoryMetrics.h"
+#include "js/PropertyKey.h"
 #include "js/TemplateLib.h"
 #include "js/Utility.h"
 #include "js/Value.h"
 #include "js/Vector.h"
 
 /*
  * Verify that our public (and intended to be public, versus being that way
  * because we haven't made them private yet) headers don't define
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -24,16 +24,17 @@
 #include "jsalloc.h"
 #include "jspubtd.h"
 #include "jsutil.h"
 
 #include "gc/Root.h"
 #include "js/Anchor.h"
 #include "js/CharacterEncoding.h"
 #include "js/HashTable.h"
+#include "js/PropertyKey.h"
 #include "js/Utility.h"
 #include "js/Value.h"
 #include "js/Vector.h"
 
 /************************************************************************/
 
 namespace JS {
 
--- a/js/src/vm/ObjectImpl.cpp
+++ b/js/src/vm/ObjectImpl.cpp
@@ -3,21 +3,24 @@
  *
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 
-#include "gc/Barrier-inl.h"
 #include "js/TemplateLib.h"
+#include "js/Value.h"
 #include "vm/Debugger.h"
 #include "vm/ObjectImpl.h"
 
+#include "jsatominlines.h"
+
+#include "gc/Barrier-inl.h"
 #include "vm/ObjectImpl-inl.h"
 #include "vm/Shape-inl.h"
 
 using namespace js;
 
 PropDesc::PropDesc()
   : pd_(UndefinedValue()),
     value_(UndefinedValue()),
new file mode 100644
--- /dev/null
+++ b/js/src/vm/PropertyKey.cpp
@@ -0,0 +1,35 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* PropertyKey implementation details. */
+
+#include "mozilla/Assertions.h"
+
+#include "gc/Root.h"
+#include "js/PropertyKey.h"
+#include "js/Value.h"
+#include "vm/String.h"
+
+using namespace js;
+
+bool
+JS::detail::ToPropertyKeySlow(JSContext *cx, HandleValue v, PropertyKey *key)
+{
+    MOZ_ASSERT_IF(v.isInt32(), v.toInt32() < 0);
+
+    RootedAtom atom(cx);
+    if (!ToAtom<CanGC>(cx, v))
+        return false;
+
+    uint32_t index;
+    if (atom->isIndex(&index)) {
+        *key = PropertyKey(index);
+        return true;
+    }
+
+    key->v.setString(atom->asPropertyName());
+    return true;
+}