This commit is contained in:
+31
-12
@@ -992,6 +992,7 @@ static sxi32 VmOverloadDominates(ph7_vm *pVm, ph7_value *aArg, ph7_vm_func *pFir
|
|||||||
/* Forward declaration */
|
/* Forward declaration */
|
||||||
#define VM_EXEC_INCLUDE 2
|
#define VM_EXEC_INCLUDE 2
|
||||||
#define VM_EXEC_HANDLER 4
|
#define VM_EXEC_HANDLER 4
|
||||||
|
#define VM_EXEC_EVAL 8
|
||||||
#define VM_INCLUDE_RETURN 3
|
#define VM_INCLUDE_RETURN 3
|
||||||
#define VM_INCLUDE_JUMP 4
|
#define VM_INCLUDE_JUMP 4
|
||||||
#define VM_INCLUDE_EXCEPTION 5
|
#define VM_INCLUDE_EXCEPTION 5
|
||||||
@@ -2854,7 +2855,7 @@ static sxi32 VmByteCodeExec(
|
|||||||
ph7_value *pStack, /* Operand stack */
|
ph7_value *pStack, /* Operand stack */
|
||||||
int nTos, /* Top entry in the operand stack (usually -1) */
|
int nTos, /* Top entry in the operand stack (usually -1) */
|
||||||
ph7_value *pResult, /* Store program return value here. NULL otherwise */
|
ph7_value *pResult, /* Store program return value here. NULL otherwise */
|
||||||
int iExecFlags /* Callback (1), included statements or exception handler */
|
int iExecFlags /* Callback (1), included statements, handler or eval */
|
||||||
) {
|
) {
|
||||||
VmInstr *pInstr;
|
VmInstr *pInstr;
|
||||||
ph7_value *pTos;
|
ph7_value *pTos;
|
||||||
@@ -6170,6 +6171,7 @@ Resume:
|
|||||||
/* Release the call context */
|
/* Release the call context */
|
||||||
VmReleaseCallContext(&sCtx);
|
VmReleaseCallContext(&sCtx);
|
||||||
if(rc == PH7_ABORT) {
|
if(rc == PH7_ABORT) {
|
||||||
|
PH7_MemObjRelease(&sRet);
|
||||||
goto Abort;
|
goto Abort;
|
||||||
}
|
}
|
||||||
if(pInstr->iP1 > 0) {
|
if(pInstr->iP1 > 0) {
|
||||||
@@ -6179,6 +6181,15 @@ Resume:
|
|||||||
/* Save foreign function return value */
|
/* Save foreign function return value */
|
||||||
PH7_MemObjStore(&sRet, pTos);
|
PH7_MemObjStore(&sRet, pTos);
|
||||||
PH7_MemObjRelease(&sRet);
|
PH7_MemObjRelease(&sRet);
|
||||||
|
if(rc == PH7_EXCEPTION) {
|
||||||
|
PH7_MemObjStore(pTos, &sTransfer);
|
||||||
|
/* Keep a NULL result if an uncaught handler resumes this
|
||||||
|
* expression. Region unwind still discards interrupted operands. */
|
||||||
|
PH7_MemObjRelease(pTos);
|
||||||
|
iTransfer = VM_TRANSFER_THROW;
|
||||||
|
nTarget = pc + 1;
|
||||||
|
goto Unwind;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -6306,7 +6317,7 @@ Unwind:
|
|||||||
goto Resume;
|
goto Resume;
|
||||||
}
|
}
|
||||||
if(iTransfer == VM_TRANSFER_THROW) {
|
if(iTransfer == VM_TRANSFER_THROW) {
|
||||||
if(SySetUsed(&pVm->aException) == 0 && (iExecFlags & (VM_EXEC_HANDLER | VM_EXEC_INCLUDE)) == 0) {
|
if(SySetUsed(&pVm->aException) == 0 && (iExecFlags & (VM_EXEC_HANDLER | VM_EXEC_INCLUDE | VM_EXEC_EVAL)) == 0) {
|
||||||
/* A nonfatal handler resumes this iteration with its bindings intact. */
|
/* A nonfatal handler resumes this iteration with its bindings intact. */
|
||||||
rc = VmUncaughtException(pVm, (sTransfer.nType & MEMOBJ_OBJ) ? (ph7_class_instance *)sTransfer.x.pOther : 0);
|
rc = VmUncaughtException(pVm, (sTransfer.nType & MEMOBJ_OBJ) ? (ph7_class_instance *)sTransfer.x.pOther : 0);
|
||||||
if(rc == PH7_ABORT) {
|
if(rc == PH7_ABORT) {
|
||||||
@@ -6325,9 +6336,10 @@ Unwind:
|
|||||||
/* Only the selected explicit value is checked against the return contract.
|
/* Only the selected explicit value is checked against the return contract.
|
||||||
* A bare return keeps NULL. An include directly borrowing the active method
|
* A bare return keeps NULL. An include directly borrowing the active method
|
||||||
* frame has no enclosing region left to override its result; otherwise it
|
* frame has no enclosing region left to override its result; otherwise it
|
||||||
* defers this check to the owner, just like a handler. */
|
* defers this check to the owner, just like a handler. Eval has its own
|
||||||
|
* dynamic return contract, even when borrowing an active owner frame. */
|
||||||
if(bReturnValue && (pEntryFrame->iFlags & VM_FRAME_ACTIVE) &&
|
if(bReturnValue && (pEntryFrame->iFlags & VM_FRAME_ACTIVE) &&
|
||||||
(iExecFlags & VM_EXEC_HANDLER) == 0) {
|
(iExecFlags & (VM_EXEC_HANDLER | VM_EXEC_EVAL)) == 0) {
|
||||||
ph7_vm_func *pFunc = (ph7_vm_func *)pEntryFrame->pUserData;
|
ph7_vm_func *pFunc = (ph7_vm_func *)pEntryFrame->pUserData;
|
||||||
if(pFunc->nType & MEMOBJ_NAMED) {
|
if(pFunc->nType & MEMOBJ_NAMED) {
|
||||||
PH7_VmTypeClass(pVm, pFunc->nType, TRUE);
|
PH7_VmTypeClass(pVm, pFunc->nType, TRUE);
|
||||||
@@ -10162,13 +10174,22 @@ static sxi32 VmEvalChunk(
|
|||||||
/* Assume a boolean true return value */
|
/* Assume a boolean true return value */
|
||||||
PH7_MemObjInitFromBool(pVm, &sResult, 1);
|
PH7_MemObjInitFromBool(pVm, &sResult, 1);
|
||||||
/* Execute the compiled chunk */
|
/* Execute the compiled chunk */
|
||||||
if(bInclude) {
|
if(bInclude || iFlags == PH7_AERSCRIPT_CHNK) {
|
||||||
ph7_value *pStack = VmNewOperandStack(pVm, SySetUsed(&aByteCode));
|
ph7_value *pStack = VmNewOperandStack(pVm, SySetUsed(&aByteCode));
|
||||||
if(pStack == 0) {
|
if(pStack == 0) {
|
||||||
rc = SXERR_MEM;
|
rc = SXERR_MEM;
|
||||||
} else {
|
} else {
|
||||||
|
/* A nested call must return its exception here before the caller's
|
||||||
|
* regions (or uncaught handler) consume it. */
|
||||||
|
ph7_exception *pBoundary = 0;
|
||||||
|
if(!bInclude && SySetPut(&pVm->aException, &pBoundary) != SXRET_OK) {
|
||||||
|
PH7_VmMemoryError(pVm);
|
||||||
|
}
|
||||||
rc = VmByteCodeExec(pVm, (VmInstr *)SySetBasePtr(&aByteCode), pStack, -1,
|
rc = VmByteCodeExec(pVm, (VmInstr *)SySetBasePtr(&aByteCode), pStack, -1,
|
||||||
&sResult, VM_EXEC_INCLUDE);
|
&sResult, bInclude ? VM_EXEC_INCLUDE : VM_EXEC_EVAL);
|
||||||
|
if(!bInclude) {
|
||||||
|
SySetPop(&pVm->aException);
|
||||||
|
}
|
||||||
SyMemBackendFree(&pVm->sAllocator, pStack);
|
SyMemBackendFree(&pVm->sAllocator, pStack);
|
||||||
if((rc == VM_INCLUDE_RETURN || rc == VM_RETURN_VOID || rc == VM_INCLUDE_JUMP || rc == VM_INCLUDE_EXCEPTION) && pResult) {
|
if((rc == VM_INCLUDE_RETURN || rc == VM_RETURN_VOID || rc == VM_INCLUDE_JUMP || rc == VM_INCLUDE_EXCEPTION) && pResult) {
|
||||||
PH7_MemObjStore(&sResult, pResult);
|
PH7_MemObjStore(&sResult, pResult);
|
||||||
@@ -10189,7 +10210,7 @@ Cleanup:
|
|||||||
/* Cleanup the mess left behind */
|
/* Cleanup the mess left behind */
|
||||||
pVm->pByteContainer = pByteCode;
|
pVm->pByteContainer = pByteCode;
|
||||||
SySetRelease(&aByteCode);
|
SySetRelease(&aByteCode);
|
||||||
return bRequire || bInclude ? rc : SXRET_OK;
|
return bRequire || bInclude || rc == PH7_EXCEPTION || rc == PH7_ABORT ? rc : SXRET_OK;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* value eval(string $code)
|
* value eval(string $code)
|
||||||
@@ -10197,9 +10218,8 @@ Cleanup:
|
|||||||
* Parameter
|
* Parameter
|
||||||
* code: PHP code to evaluate.
|
* code: PHP code to evaluate.
|
||||||
* Return
|
* Return
|
||||||
* eval() returns NULL unless return is called in the evaluated code, in which case
|
* eval() returns TRUE unless return is called in the evaluated code, in which case
|
||||||
* the value passed to return is returned. If there is a parse error in the evaluated
|
* the value passed to return is returned. Missing or empty input returns NULL.
|
||||||
* code, eval() returns FALSE and execution of the following code continues normally.
|
|
||||||
*/
|
*/
|
||||||
static int vm_builtin_eval(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
static int vm_builtin_eval(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||||
SyString sChunk; /* Chunk to evaluate */
|
SyString sChunk; /* Chunk to evaluate */
|
||||||
@@ -10216,8 +10236,7 @@ static int vm_builtin_eval(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
|||||||
return SXRET_OK;
|
return SXRET_OK;
|
||||||
}
|
}
|
||||||
/* Eval the chunk */
|
/* Eval the chunk */
|
||||||
VmEvalChunk(pCtx->pVm, &(*pCtx), &sChunk, PH7_AERSCRIPT_CHNK, 0, 0);
|
return VmEvalChunk(pCtx->pVm, &(*pCtx), &sChunk, PH7_AERSCRIPT_CHNK, 0, 0);
|
||||||
return SXRET_OK;
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Check if a file path is already included.
|
* Check if a file path is already included.
|
||||||
|
|||||||
Reference in New Issue
Block a user