mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-07 00:08:39 +09:00
1339395 - Part 3: Add BytecodeEmitter support for object rest and spread properties.
This commit is contained in:
parent
85350c0655
commit
1e126cc49d
4 changed files with 339 additions and 45 deletions
|
|
@ -229,6 +229,69 @@ function GetInternalError(msg) {
|
|||
// To be used when a function is required but calling it shouldn't do anything.
|
||||
function NullFunction() {}
|
||||
|
||||
// Object Rest/Spread Properties proposal
|
||||
// Abstract operation: CopyDataProperties (target, source, excluded)
|
||||
function CopyDataProperties(target, source, excluded) {
|
||||
// Step 1.
|
||||
assert(IsObject(target), "target is an object");
|
||||
|
||||
// Step 2.
|
||||
assert(IsObject(excluded), "excluded is an object");
|
||||
|
||||
// Steps 3, 6.
|
||||
if (source === undefined || source === null)
|
||||
return;
|
||||
|
||||
// Step 4.a.
|
||||
source = ToObject(source);
|
||||
|
||||
// Step 4.b.
|
||||
var keys = OwnPropertyKeys(source, JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS);
|
||||
|
||||
// Step 5.
|
||||
for (var index = 0; index < keys.length; index++) {
|
||||
var key = keys[index];
|
||||
|
||||
// We abbreviate this by calling propertyIsEnumerable which is faster
|
||||
// and returns false for not defined properties.
|
||||
if (!callFunction(std_Object_hasOwnProperty, key, excluded) && callFunction(std_Object_propertyIsEnumerable, source, key))
|
||||
_DefineDataProperty(target, key, source[key]);
|
||||
}
|
||||
|
||||
// Step 6 (Return).
|
||||
}
|
||||
|
||||
// Object Rest/Spread Properties proposal
|
||||
// Abstract operation: CopyDataProperties (target, source, excluded)
|
||||
function CopyDataPropertiesUnfiltered(target, source) {
|
||||
// Step 1.
|
||||
assert(IsObject(target), "target is an object");
|
||||
|
||||
// Step 2 (Not applicable).
|
||||
|
||||
// Steps 3, 6.
|
||||
if (source === undefined || source === null)
|
||||
return;
|
||||
|
||||
// Step 4.a.
|
||||
source = ToObject(source);
|
||||
|
||||
// Step 4.b.
|
||||
var keys = OwnPropertyKeys(source, JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS);
|
||||
|
||||
// Step 5.
|
||||
for (var index = 0; index < keys.length; index++) {
|
||||
var key = keys[index];
|
||||
|
||||
// We abbreviate this by calling propertyIsEnumerable which is faster
|
||||
// and returns false for not defined properties.
|
||||
if (callFunction(std_Object_propertyIsEnumerable, source, key))
|
||||
_DefineDataProperty(target, key, source[key]);
|
||||
}
|
||||
|
||||
// Step 6 (Return).
|
||||
}
|
||||
|
||||
/*************************************** Testing functions ***************************************/
|
||||
function outer() {
|
||||
return function inner() {
|
||||
|
|
|
|||
|
|
@ -5814,41 +5814,78 @@ BytecodeEmitter::emitDestructuringOpsObject(ParseNode* pattern, DestructuringFla
|
|||
if (!emitRequireObjectCoercible()) // ... RHS
|
||||
return false;
|
||||
|
||||
for (ParseNode* member = pattern->pn_head; member; member = member->pn_next) {
|
||||
if (member->isKind(PNK_SPREAD)) {
|
||||
// FIXME: Implement
|
||||
continue;
|
||||
}
|
||||
bool needsRestPropertyExcludedSet = pattern->pn_count > 1 &&
|
||||
pattern->last()->isKind(PNK_SPREAD);
|
||||
if (needsRestPropertyExcludedSet) {
|
||||
if (!emitDestructuringObjRestExclusionSet(pattern)) // ... RHS SET
|
||||
return false;
|
||||
|
||||
if (!emit1(JSOP_SWAP)) // ... SET RHS
|
||||
return false;
|
||||
}
|
||||
|
||||
for (ParseNode* member = pattern->pn_head; member; member = member->pn_next) {
|
||||
ParseNode* subpattern;
|
||||
if (member->isKind(PNK_MUTATEPROTO))
|
||||
if (member->isKind(PNK_MUTATEPROTO) || member->isKind(PNK_SPREAD))
|
||||
subpattern = member->pn_kid;
|
||||
else
|
||||
subpattern = member->pn_right;
|
||||
|
||||
ParseNode* lhs = subpattern;
|
||||
MOZ_ASSERT_IF(member->isKind(PNK_SPREAD), !lhs->isKind(PNK_ASSIGN));
|
||||
if (lhs->isKind(PNK_ASSIGN))
|
||||
lhs = lhs->pn_left;
|
||||
|
||||
size_t emitted;
|
||||
if (!emitDestructuringLHSRef(lhs, &emitted)) // ... RHS *LREF
|
||||
if (!emitDestructuringLHSRef(lhs, &emitted)) // ... *SET RHS *LREF
|
||||
return false;
|
||||
|
||||
// Duplicate the value being destructured to use as a reference base.
|
||||
if (emitted) {
|
||||
if (!emitDupAt(emitted)) // ... RHS *LREF RHS
|
||||
if (!emitDupAt(emitted)) // ... *SET RHS *LREF RHS
|
||||
return false;
|
||||
} else {
|
||||
if (!emit1(JSOP_DUP)) // ... RHS RHS
|
||||
if (!emit1(JSOP_DUP)) // ... *SET RHS RHS
|
||||
return false;
|
||||
}
|
||||
|
||||
if (member->isKind(PNK_SPREAD)) {
|
||||
if (!updateSourceCoordNotes(member->pn_pos.begin))
|
||||
return false;
|
||||
|
||||
if (!emitNewInit(JSProto_Object)) // ... *SET RHS *LREF RHS TARGET
|
||||
return false;
|
||||
if (!emit1(JSOP_DUP)) // ... *SET RHS *LREF RHS TARGET TARGET
|
||||
return false;
|
||||
if (!emit2(JSOP_PICK, 2)) // ... *SET RHS *LREF TARGET TARGET RHS
|
||||
return false;
|
||||
|
||||
if (needsRestPropertyExcludedSet) {
|
||||
if (!emit2(JSOP_PICK, emitted + 4)) // ... RHS *LREF TARGET TARGET RHS SET
|
||||
return false;
|
||||
}
|
||||
|
||||
CopyOption option = needsRestPropertyExcludedSet
|
||||
? CopyOption::Filtered
|
||||
: CopyOption::Unfiltered;
|
||||
if (!emitCopyDataProperties(option)) // ... RHS *LREF TARGET
|
||||
return false;
|
||||
|
||||
// Destructure TARGET per this member's lhs.
|
||||
if (!emitSetOrInitializeDestructuring(lhs, flav)) // ... RHS
|
||||
return false;
|
||||
|
||||
MOZ_ASSERT(member == pattern->last(), "Rest property is always last");
|
||||
break;
|
||||
}
|
||||
|
||||
// Now push the property name currently being matched, which is the
|
||||
// current property name "label" on the left of a colon in the object
|
||||
// initialiser.
|
||||
bool needsGetElem = true;
|
||||
|
||||
if (member->isKind(PNK_MUTATEPROTO)) {
|
||||
if (!emitAtomOp(cx->names().proto, JSOP_GETPROP)) // ... RHS *LREF PROP
|
||||
if (!emitAtomOp(cx->names().proto, JSOP_GETPROP)) // ... *SET RHS *LREF PROP
|
||||
return false;
|
||||
needsGetElem = false;
|
||||
} else {
|
||||
|
|
@ -5856,7 +5893,7 @@ BytecodeEmitter::emitDestructuringOpsObject(ParseNode* pattern, DestructuringFla
|
|||
|
||||
ParseNode* key = member->pn_left;
|
||||
if (key->isKind(PNK_NUMBER)) {
|
||||
if (!emitNumberOp(key->pn_dval)) // ... RHS *LREF RHS KEY
|
||||
if (!emitNumberOp(key->pn_dval)) // ... *SET RHS *LREF RHS KEY
|
||||
return false;
|
||||
} else if (key->isKind(PNK_OBJECT_PROPERTY_NAME) || key->isKind(PNK_STRING)) {
|
||||
PropertyName* name = key->pn_atom->asPropertyName();
|
||||
|
|
@ -5866,30 +5903,142 @@ BytecodeEmitter::emitDestructuringOpsObject(ParseNode* pattern, DestructuringFla
|
|||
// as indexes for simplification of downstream analysis.
|
||||
jsid id = NameToId(name);
|
||||
if (id != IdToTypeId(id)) {
|
||||
if (!emitTree(key)) // ... RHS *LREF RHS KEY
|
||||
if (!emitTree(key)) // ... *SET RHS *LREF RHS KEY
|
||||
return false;
|
||||
} else {
|
||||
if (!emitAtomOp(name, JSOP_GETPROP)) // ... RHS *LREF PROP
|
||||
if (!emitAtomOp(name, JSOP_GETPROP)) // ... *SET RHS *LREF PROP
|
||||
return false;
|
||||
needsGetElem = false;
|
||||
}
|
||||
} else {
|
||||
if (!emitComputedPropertyName(key)) // ... RHS *LREF RHS KEY
|
||||
if (!emitComputedPropertyName(key)) // ... *SET RHS *LREF RHS KEY
|
||||
return false;
|
||||
|
||||
// Add the computed property key to the exclusion set.
|
||||
if (needsRestPropertyExcludedSet) {
|
||||
if (!emitDupAt(emitted + 3)) // ... SET RHS *LREF RHS KEY SET
|
||||
return false;
|
||||
if (!emitDupAt(1)) // ... SET RHS *LREF RHS KEY SET KEY
|
||||
return false;
|
||||
if (!emit1(JSOP_UNDEFINED)) // ... SET RHS *LREF RHS KEY SET KEY UNDEFINED
|
||||
return false;
|
||||
if (!emit1(JSOP_INITELEM)) // ... SET RHS *LREF RHS KEY SET
|
||||
return false;
|
||||
if (!emit1(JSOP_POP)) // ... SET RHS *LREF RHS KEY
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get the property value if not done already.
|
||||
if (needsGetElem && !emitElemOpBase(JSOP_GETELEM)) // ... RHS *LREF PROP
|
||||
if (needsGetElem && !emitElemOpBase(JSOP_GETELEM)) // ... *SET RHS *LREF PROP
|
||||
return false;
|
||||
|
||||
if (subpattern->isKind(PNK_ASSIGN)) {
|
||||
if (!emitDefault(subpattern->pn_right, lhs)) // ... RHS *LREF VALUE
|
||||
if (!emitDefault(subpattern->pn_right, lhs)) // ... *SET RHS *LREF VALUE
|
||||
return false;
|
||||
}
|
||||
|
||||
// Destructure PROP per this member's lhs.
|
||||
if (!emitSetOrInitializeDestructuring(subpattern, flav)) // ... RHS
|
||||
if (!emitSetOrInitializeDestructuring(subpattern, flav)) // ... *SET RHS
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitDestructuringObjRestExclusionSet(ParseNode* pattern)
|
||||
{
|
||||
MOZ_ASSERT(pattern->isKind(PNK_OBJECT));
|
||||
MOZ_ASSERT(pattern->isArity(PN_LIST));
|
||||
MOZ_ASSERT(pattern->last()->isKind(PNK_SPREAD));
|
||||
|
||||
ptrdiff_t offset = this->offset();
|
||||
if (!emitNewInit(JSProto_Object))
|
||||
return false;
|
||||
|
||||
// Try to construct the shape of the object as we go, so we can emit a
|
||||
// JSOP_NEWOBJECT with the final shape instead.
|
||||
// In the case of computed property names and indices, we cannot fix the
|
||||
// shape at bytecode compile time. When the shape cannot be determined,
|
||||
// |obj| is nulled out.
|
||||
|
||||
// No need to do any guessing for the object kind, since we know the upper
|
||||
// bound of how many properties we plan to have.
|
||||
gc::AllocKind kind = gc::GetGCObjectKind(pattern->pn_count - 1);
|
||||
RootedPlainObject obj(cx, NewBuiltinClassInstance<PlainObject>(cx, kind, TenuredObject));
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
RootedAtom pnatom(cx);
|
||||
for (ParseNode* member = pattern->pn_head; member; member = member->pn_next) {
|
||||
if (member->isKind(PNK_SPREAD))
|
||||
break;
|
||||
|
||||
bool isIndex = false;
|
||||
if (member->isKind(PNK_MUTATEPROTO)) {
|
||||
pnatom.set(cx->names().proto);
|
||||
} else {
|
||||
ParseNode* key = member->pn_left;
|
||||
if (key->isKind(PNK_NUMBER)) {
|
||||
if (!emitNumberOp(key->pn_dval))
|
||||
return false;
|
||||
isIndex = true;
|
||||
} else if (key->isKind(PNK_OBJECT_PROPERTY_NAME) || key->isKind(PNK_STRING)) {
|
||||
// The parser already checked for atoms representing indexes and
|
||||
// used PNK_NUMBER instead, but also watch for ids which TI treats
|
||||
// as indexes for simplification of downstream analysis.
|
||||
jsid id = NameToId(key->pn_atom->asPropertyName());
|
||||
if (id != IdToTypeId(id)) {
|
||||
if (!emitTree(key))
|
||||
return false;
|
||||
isIndex = true;
|
||||
} else {
|
||||
pnatom.set(key->pn_atom);
|
||||
}
|
||||
} else {
|
||||
// Otherwise this is a computed property name which needs to
|
||||
// be added dynamically.
|
||||
obj.set(nullptr);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize elements with |undefined|.
|
||||
if (!emit1(JSOP_UNDEFINED))
|
||||
return false;
|
||||
|
||||
if (isIndex) {
|
||||
obj.set(nullptr);
|
||||
if (!emit1(JSOP_INITELEM))
|
||||
return false;
|
||||
} else {
|
||||
uint32_t index;
|
||||
if (!makeAtomIndex(pnatom, &index))
|
||||
return false;
|
||||
|
||||
if (obj) {
|
||||
MOZ_ASSERT(!obj->inDictionaryMode());
|
||||
Rooted<jsid> id(cx, AtomToId(pnatom));
|
||||
if (!NativeDefineProperty(cx, obj, id, UndefinedHandleValue, nullptr, nullptr,
|
||||
JSPROP_ENUMERATE))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (obj->inDictionaryMode())
|
||||
obj.set(nullptr);
|
||||
}
|
||||
|
||||
if (!emitIndex32(JSOP_INITPROP, index))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (obj) {
|
||||
// The object survived and has a predictable shape: update the
|
||||
// original bytecode.
|
||||
if (!replaceNewInitWithNewObject(obj, offset))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -6770,6 +6919,53 @@ BytecodeEmitter::emitRequireObjectCoercible()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitCopyDataProperties(CopyOption option)
|
||||
{
|
||||
DebugOnly<int32_t> depth = this->stackDepth;
|
||||
|
||||
uint32_t argc;
|
||||
if (option == CopyOption::Filtered) {
|
||||
MOZ_ASSERT(depth > 2); // TARGET SOURCE SET
|
||||
argc = 3;
|
||||
|
||||
if (!emitAtomOp(cx->names().CopyDataProperties,
|
||||
JSOP_GETINTRINSIC)) // TARGET SOURCE SET COPYDATAPROPERTIES
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT(depth > 1); // TARGET SOURCE
|
||||
argc = 2;
|
||||
|
||||
if (!emitAtomOp(cx->names().CopyDataPropertiesUnfiltered,
|
||||
JSOP_GETINTRINSIC)) // TARGET SOURCE COPYDATAPROPERTIES
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!emit1(JSOP_UNDEFINED)) // TARGET SOURCE *SET COPYDATAPROPERTIES UNDEFINED
|
||||
return false;
|
||||
if (!emit2(JSOP_PICK, argc + 1)) // SOURCE *SET COPYDATAPROPERTIES UNDEFINED TARGET
|
||||
return false;
|
||||
if (!emit2(JSOP_PICK, argc + 1)) // *SET COPYDATAPROPERTIES UNDEFINED TARGET SOURCE
|
||||
return false;
|
||||
if (option == CopyOption::Filtered) {
|
||||
if (!emit2(JSOP_PICK, argc + 1)) // COPYDATAPROPERTIES UNDEFINED TARGET SOURCE SET
|
||||
return false;
|
||||
}
|
||||
if (!emitCall(JSOP_CALL_IGNORES_RV, argc)) // IGNORED
|
||||
return false;
|
||||
checkTypeSet(JSOP_CALL_IGNORES_RV);
|
||||
|
||||
if (!emit1(JSOP_POP)) // -
|
||||
return false;
|
||||
|
||||
MOZ_ASSERT(depth - int(argc) == this->stackDepth);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitIterator()
|
||||
{
|
||||
|
|
@ -9456,8 +9652,17 @@ BytecodeEmitter::emitPropertyList(ParseNode* pn, MutableHandlePlainObject objp,
|
|||
|
||||
if (propdef->isKind(PNK_SPREAD)) {
|
||||
MOZ_ASSERT(type == ObjectLiteral);
|
||||
|
||||
if (!emit1(JSOP_DUP))
|
||||
return false;
|
||||
|
||||
if (!emitTree(propdef->pn_kid))
|
||||
return false;
|
||||
|
||||
if (!emitCopyDataProperties(CopyOption::Unfiltered))
|
||||
return false;
|
||||
|
||||
objp.set(nullptr);
|
||||
// FIXME: implement
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -9487,7 +9692,7 @@ BytecodeEmitter::emitPropertyList(ParseNode* pn, MutableHandlePlainObject objp,
|
|||
|
||||
// The parser already checked for atoms representing indexes and
|
||||
// used PNK_NUMBER instead, but also watch for ids which TI treats
|
||||
// as indexes for simpliciation of downstream analysis.
|
||||
// as indexes for simplification of downstream analysis.
|
||||
jsid id = NameToId(key->pn_atom->asPropertyName());
|
||||
if (id != IdToTypeId(id)) {
|
||||
if (!emitTree(key))
|
||||
|
|
@ -9574,8 +9779,7 @@ BytecodeEmitter::emitPropertyList(ParseNode* pn, MutableHandlePlainObject objp,
|
|||
MOZ_ASSERT(!IsHiddenInitOp(op));
|
||||
MOZ_ASSERT(!objp->inDictionaryMode());
|
||||
Rooted<jsid> id(cx, AtomToId(key->pn_atom));
|
||||
RootedValue undefinedValue(cx, UndefinedValue());
|
||||
if (!NativeDefineProperty(cx, objp, id, undefinedValue, nullptr, nullptr,
|
||||
if (!NativeDefineProperty(cx, objp, id, UndefinedHandleValue, nullptr, nullptr,
|
||||
JSPROP_ENUMERATE))
|
||||
{
|
||||
return false;
|
||||
|
|
@ -9618,15 +9822,16 @@ BytecodeEmitter::emitObject(ParseNode* pn)
|
|||
if (!emitNewInit(JSProto_Object))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Try to construct the shape of the object as we go, so we can emit a
|
||||
* JSOP_NEWOBJECT with the final shape instead.
|
||||
*/
|
||||
RootedPlainObject obj(cx);
|
||||
// No need to do any guessing for the object kind, since we know exactly
|
||||
// how many properties we plan to have.
|
||||
// Try to construct the shape of the object as we go, so we can emit a
|
||||
// JSOP_NEWOBJECT with the final shape instead.
|
||||
// In the case of computed property names and indices, we cannot fix the
|
||||
// shape at bytecode compile time. When the shape cannot be determined,
|
||||
// |obj| is nulled out.
|
||||
|
||||
// No need to do any guessing for the object kind, since we know the upper
|
||||
// bound of how many properties we plan to have.
|
||||
gc::AllocKind kind = gc::GetGCObjectKind(pn->pn_count);
|
||||
obj = NewBuiltinClassInstance<PlainObject>(cx, kind, TenuredObject);
|
||||
RootedPlainObject obj(cx, NewBuiltinClassInstance<PlainObject>(cx, kind, TenuredObject));
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
|
|
@ -9634,29 +9839,38 @@ BytecodeEmitter::emitObject(ParseNode* pn)
|
|||
return false;
|
||||
|
||||
if (obj) {
|
||||
/*
|
||||
* The object survived and has a predictable shape: update the original
|
||||
* bytecode.
|
||||
*/
|
||||
ObjectBox* objbox = parser->newObjectBox(obj);
|
||||
if (!objbox)
|
||||
// The object survived and has a predictable shape: update the original
|
||||
// bytecode.
|
||||
if (!replaceNewInitWithNewObject(obj, offset))
|
||||
return false;
|
||||
|
||||
static_assert(JSOP_NEWINIT_LENGTH == JSOP_NEWOBJECT_LENGTH,
|
||||
"newinit and newobject must have equal length to edit in-place");
|
||||
|
||||
uint32_t index = objectList.add(objbox);
|
||||
jsbytecode* code = this->code(offset);
|
||||
code[0] = JSOP_NEWOBJECT;
|
||||
code[1] = jsbytecode(index >> 24);
|
||||
code[2] = jsbytecode(index >> 16);
|
||||
code[3] = jsbytecode(index >> 8);
|
||||
code[4] = jsbytecode(index);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::replaceNewInitWithNewObject(JSObject* obj, ptrdiff_t offset)
|
||||
{
|
||||
ObjectBox* objbox = parser->newObjectBox(obj);
|
||||
if (!objbox)
|
||||
return false;
|
||||
|
||||
static_assert(JSOP_NEWINIT_LENGTH == JSOP_NEWOBJECT_LENGTH,
|
||||
"newinit and newobject must have equal length to edit in-place");
|
||||
|
||||
uint32_t index = objectList.add(objbox);
|
||||
jsbytecode* code = this->code(offset);
|
||||
|
||||
MOZ_ASSERT(code[0] == JSOP_NEWINIT);
|
||||
code[0] = JSOP_NEWOBJECT;
|
||||
code[1] = jsbytecode(index >> 24);
|
||||
code[2] = jsbytecode(index >> 16);
|
||||
code[3] = jsbytecode(index >> 8);
|
||||
code[4] = jsbytecode(index);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitArrayComp(ParseNode* pn)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -540,6 +540,8 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitFunction(ParseNode* pn, bool needsProto = false);
|
||||
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitObject(ParseNode* pn);
|
||||
|
||||
MOZ_MUST_USE bool replaceNewInitWithNewObject(JSObject* obj, ptrdiff_t offset);
|
||||
|
||||
MOZ_MUST_USE bool emitHoistedFunctionsInList(ParseNode* pn);
|
||||
|
||||
MOZ_MUST_USE bool emitPropertyList(ParseNode* pn, MutableHandlePlainObject objp,
|
||||
|
|
@ -667,6 +669,10 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
// []/{} expression).
|
||||
MOZ_MUST_USE bool emitSetOrInitializeDestructuring(ParseNode* target, DestructuringFlavor flav);
|
||||
|
||||
// emitDestructuringObjRestExclusionSet emits the property exclusion set
|
||||
// for the rest-property in an object pattern.
|
||||
MOZ_MUST_USE bool emitDestructuringObjRestExclusionSet(ParseNode* pattern);
|
||||
|
||||
// emitDestructuringOps assumes the to-be-destructured value has been
|
||||
// pushed on the stack and emits code to destructure each part of a [] or
|
||||
// {} lhs expression.
|
||||
|
|
@ -684,6 +690,15 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
// object, with no overall effect on the stack.
|
||||
MOZ_MUST_USE bool emitRequireObjectCoercible();
|
||||
|
||||
enum class CopyOption {
|
||||
Filtered, Unfiltered
|
||||
};
|
||||
|
||||
// Calls either the |CopyDataProperties| or the
|
||||
// |CopyDataPropertiesUnfiltered| intrinsic function, consumes three (or
|
||||
// two in the latter case) elements from the stack.
|
||||
MOZ_MUST_USE bool emitCopyDataProperties(CopyOption option);
|
||||
|
||||
// emitIterator expects the iterable to already be on the stack.
|
||||
// It will replace that stack value with the corresponding iterator
|
||||
MOZ_MUST_USE bool emitIterator();
|
||||
|
|
|
|||
|
|
@ -71,6 +71,8 @@
|
|||
macro(constructor, constructor, "constructor") \
|
||||
macro(continue, continue_, "continue") \
|
||||
macro(ConvertAndCopyTo, ConvertAndCopyTo, "ConvertAndCopyTo") \
|
||||
macro(CopyDataProperties, CopyDataProperties, "CopyDataProperties") \
|
||||
macro(CopyDataPropertiesUnfiltered, CopyDataPropertiesUnfiltered, "CopyDataPropertiesUnfiltered") \
|
||||
macro(copyWithin, copyWithin, "copyWithin") \
|
||||
macro(count, count, "count") \
|
||||
macro(CreateResolvingFunctions, CreateResolvingFunctions, "CreateResolvingFunctions") \
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue