Skip to content

Commit 106960e

Browse files
BUGFIX: Multiple bugs related to object construction and prototypes.
1 parent d9a82e6 commit 106960e

File tree

2 files changed

+60
-19
lines changed

2 files changed

+60
-19
lines changed

mvmCodegen.cpp

Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ void functionCodegen (Ref<AstNode> statement, CodegenState* pState);
5959
void assignmentCodegen (Ref<AstNode> statement, CodegenState* pState);
6060
void fncallCodegen (Ref<AstNode> statement, CodegenState* pState);
6161
void thisCallCodegen (Ref<AstNode> statement, CodegenState* pState);
62+
void constructorCodegen (Ref<AstNode> statement, CodegenState* pState);
6263
void literalCodegen (Ref<AstNode> statement, CodegenState* pState);
6364
void identifierCodegen (Ref<AstNode> statement, CodegenState* pState);
6465
void arrayCodegen (Ref<AstNode> statement, CodegenState* pState);
@@ -450,34 +451,31 @@ void assignmentCodegen (Ref<AstNode> statement, CodegenState* pState)
450451
void fncallCodegen (Ref<AstNode> statement, CodegenState* pState)
451452
{
452453
if (statement->getType() == AST_NEWCALL)
453-
{
454-
//Create a new object, and pass it as 'this' reference.
455-
callCodegen("@newObj", 0, pState);
456-
}
454+
constructorCodegen(statement, pState);
457455
else
458456
{
459457
const AstNodeTypes fnExprType = statement->children()[0]->getType();
460458

461459
//If the expression to get the function reference is an object member access,
462460
//then use generate a 'this' call.
463461
if (fnExprType == AST_MEMBER_ACCESS || fnExprType == AST_ARRAY_ACCESS)
464-
{
465462
thisCallCodegen (statement, pState);
466-
return;
467-
}
468463
else
464+
{
465+
//Regular function call (no this pointer)
469466
pushUndefined(pState); //No 'this' pointer.
470-
}
471-
472-
//Parameters evaluation
473-
const int nChilds = (int)statement->children().size();
474-
for (int i = 1; i < nChilds; ++i)
475-
childCodegen(statement, i, pState);
467+
468+
//Parameters evaluation
469+
const int nChilds = (int)statement->children().size();
470+
for (int i = 1; i < nChilds; ++i)
471+
childCodegen(statement, i, pState);
476472

477-
//Evaluate function reference expression
478-
childCodegen(statement, 0, pState);
479-
480-
callInstruction (nChilds, pState);
473+
//Evaluate function reference expression
474+
childCodegen(statement, 0, pState);
475+
476+
callInstruction (nChilds, pState);
477+
}
478+
}
481479
}
482480

483481
/**
@@ -508,6 +506,41 @@ void thisCallCodegen (Ref<AstNode> statement, CodegenState* pState)
508506
callInstruction (nChilds, pState);
509507
}
510508

509+
/**
510+
* Generates code for a operator 'new' function call
511+
* @param statement
512+
* @param pState
513+
*/
514+
void constructorCodegen (Ref<AstNode> statement, CodegenState* pState)
515+
{
516+
childCodegen(statement, 0, pState); //[function]
517+
instruction8(OC_CP, pState); //[function, function]
518+
519+
//Create a new object, to pass it as 'this' reference. '@newObj' receives as
520+
//parameter the constructor function, from which it will read the object prototype.
521+
callCodegen("@newObj", 1, pState); //[function, this]
522+
523+
instruction8(OC_SWAP, pState); //[this, function]
524+
instruction8(OC_CP+1, pState); //[this, function, this]
525+
instruction8(OC_SWAP, pState); //[this, this, function]
526+
527+
//Parameters evaluation
528+
const int nChilds = (int)statement->children().size();
529+
for (int i = 1; i < nChilds; ++i)
530+
{
531+
childCodegen(statement, i, pState); //Parameter evaluation
532+
instruction8(OC_SWAP, pState); //Put function back on top
533+
}
534+
535+
//stack: [this, this, param1, param2,... paramN, function]
536+
537+
//Write call instruction
538+
callInstruction (nChilds, pState); //[this, result]
539+
540+
//Discard function result, keep 'this' (the new object)
541+
instruction8(OC_POP, pState);
542+
}
543+
511544
/**
512545
* Generates code for a literal expression.
513546
* @param statement

mvmFunctions.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,16 @@ using namespace std;
2323
*/
2424
Ref<JSValue> mvmNewObj (FunctionScope* pScope)
2525
{
26-
//TODO: Prototype???
27-
return JSObject::create(JSObject::DefaultPrototype);
26+
Ref<JSValue> constructor = pScope->getThis();
27+
Ref<JSValue> prototype = undefined();
28+
29+
if (constructor->isFunction())
30+
prototype = constructor.staticCast<JSFunction>()->get("prototype");
31+
32+
if (!prototype->isObject())
33+
return JSObject::create(); //No constructor provided. Use default prototype.
34+
else
35+
return JSObject::create(prototype.staticCast<JSObject>());
2836
}
2937

3038
/**

0 commit comments

Comments
 (0)