diff options
Diffstat (limited to 'js/src/vm/RecordTupleShared.cpp')
-rw-r--r-- | js/src/vm/RecordTupleShared.cpp | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/js/src/vm/RecordTupleShared.cpp b/js/src/vm/RecordTupleShared.cpp new file mode 100644 index 0000000000..bac0b4f45e --- /dev/null +++ b/js/src/vm/RecordTupleShared.cpp @@ -0,0 +1,134 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * 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/. */ + +#ifndef vm_RecordTupleShared_h +#define vm_RecordTupleShared_h + +#include "vm/RecordTupleShared.h" + +#include "NamespaceImports.h" +#include "builtin/RecordObject.h" +#include "builtin/TupleObject.h" +#include "js/Value.h" +#include "vm/BigIntType.h" +#include "vm/Compartment.h" +#include "vm/GlobalObject.h" +#include "vm/JSObject.h" +#include "vm/NativeObject.h" + +#include "gc/Marking-inl.h" + +namespace js { + +bool IsExtendedPrimitive(const JSObject& obj) { + return obj.is<RecordType>() || obj.is<TupleType>(); +} + +template <typename T> +JSObject* CopyExtendedPrimitiveHelper(JSContext* cx, HandleObject extPrim) { + MOZ_ASSERT(gc::MaybeForwardedObjectIs<T>(extPrim)); + Rooted<T*> in(cx, &extPrim->template as<T>()); + Rooted<T*> out(cx); + if (!T::copy(cx, in, &out)) { + return nullptr; + } + return out; +} + +JSObject* CopyExtendedPrimitive(JSContext* cx, HandleObject extPrim) { + if (gc::MaybeForwardedObjectIs<RecordType>(extPrim)) { + return CopyExtendedPrimitiveHelper<RecordType>(cx, extPrim); + } + MOZ_ASSERT(gc::MaybeForwardedObjectIs<TupleType>(extPrim)); + return CopyExtendedPrimitiveHelper<TupleType>(cx, extPrim); +} + +// Returns false if v is not a valid record/tuple element (e.g. it's an Object +// or Symbol +bool CopyRecordTupleElement(JSContext* cx, HandleValue v, + MutableHandleValue out) { + switch (v.type()) { + case JS::ValueType::Double: + case JS::ValueType::Int32: + case JS::ValueType::Undefined: + case JS::ValueType::Boolean: { + out.set(v); + break; + } + case JS::ValueType::String: { + RootedString vStr(cx, v.toString()); + JSString* copy = CopyStringPure(cx, vStr); + if (!copy) { + return false; + } + out.setString(copy); + break; + } + case JS::ValueType::BigInt: { + RootedBigInt bi(cx, v.toBigInt()); + BigInt* copy = BigInt::copy(cx, bi); + if (!copy) { + return false; + } + out.setBigInt(copy); + break; + } + case JS::ValueType::ExtendedPrimitive: { + RootedObject extPrim(cx, &v.toExtendedPrimitive()); + JSObject* copy = CopyExtendedPrimitive(cx, extPrim); + if (!copy) { + return false; + } + out.setExtendedPrimitive(*copy); + break; + } + default: + MOZ_CRASH("CopyRecordTupleElement(): unexpected element type"); + } + return true; +} + +bool gc::MaybeForwardedIsExtendedPrimitive(const JSObject& obj) { + return MaybeForwardedObjectIs<RecordType>(&obj) || + MaybeForwardedObjectIs<TupleType>(&obj); +} + +bool IsExtendedPrimitiveWrapper(const JSObject& obj) { + return obj.is<RecordObject>() || obj.is<TupleObject>(); +} + +bool ExtendedPrimitiveGetProperty(JSContext* cx, HandleObject obj, + HandleValue receiver, HandleId id, + MutableHandleValue vp) { + MOZ_ASSERT(IsExtendedPrimitive(*obj)); + + if (obj->is<RecordType>()) { + if (obj->as<RecordType>().getOwnProperty(cx, id, vp)) { + return true; + } + // If records will not have a null prototype, this should use a mehanism + // similar to tuples. + vp.set(JS::UndefinedValue()); + return true; + } + + MOZ_ASSERT(obj->is<TupleType>()); + if (obj->as<TupleType>().getOwnProperty(id, vp)) { + return true; + } + + JSObject* proto = GlobalObject::getOrCreateTuplePrototype(cx, cx->global()); + if (!proto) { + return false; + } + + Rooted<NativeObject*> rootedProto(cx, &proto->as<NativeObject>()); + return NativeGetProperty(cx, rootedProto, receiver, id, vp); +} + +} // namespace js + +#endif |