2025-03-19 21:25:58 +10:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
|
|
|
* vim: set ts=8 sw=4 et tw=99:
|
|
|
|
|
*/
|
|
|
|
|
|
2025-02-05 12:40:54 +10:00
|
|
|
#include "tests.h"
|
|
|
|
|
#include "jsdbgapi.h"
|
|
|
|
|
|
|
|
|
|
static int callCount[2] = {0, 0};
|
|
|
|
|
|
|
|
|
|
static void *
|
2025-03-19 21:25:58 +10:00
|
|
|
callCountHook(JSContext *cx, JSStackFrame *fp, JSBool before, JSBool *ok, void *closure)
|
2025-02-05 12:40:54 +10:00
|
|
|
{
|
|
|
|
|
callCount[before]++;
|
2025-03-19 21:25:58 +10:00
|
|
|
|
|
|
|
|
jsval thisv;
|
|
|
|
|
JS_GetFrameThis(cx, fp, &thisv); // assert if fp is incomplete
|
|
|
|
|
|
2025-02-05 12:40:54 +10:00
|
|
|
return cx; // any non-null value causes the hook to be called again after
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BEGIN_TEST(testDebugger_bug519719)
|
|
|
|
|
{
|
2025-03-19 21:25:58 +10:00
|
|
|
JS_SetCallHook(rt, callCountHook, NULL);
|
2025-02-05 12:40:54 +10:00
|
|
|
EXEC("function call(fn) { fn(0); }\n"
|
|
|
|
|
"function f(g) { for (var i = 0; i < 9; i++) call(g); }\n"
|
|
|
|
|
"f(Math.sin);\n" // record loop, starting in f
|
|
|
|
|
"f(Math.cos);\n"); // side exit in f -> call
|
|
|
|
|
CHECK(callCount[0] == 20);
|
|
|
|
|
CHECK(callCount[1] == 20);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
END_TEST(testDebugger_bug519719)
|
2025-03-19 21:25:58 +10:00
|
|
|
|
|
|
|
|
static void *
|
|
|
|
|
nonStrictThisHook(JSContext *cx, JSStackFrame *fp, JSBool before, JSBool *ok, void *closure)
|
|
|
|
|
{
|
|
|
|
|
if (before) {
|
|
|
|
|
bool *allWrapped = (bool *) closure;
|
|
|
|
|
jsval thisv;
|
|
|
|
|
JS_GetFrameThis(cx, fp, &thisv);
|
|
|
|
|
*allWrapped = *allWrapped && !JSVAL_IS_PRIMITIVE(thisv);
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BEGIN_TEST(testDebugger_getThisNonStrict)
|
|
|
|
|
{
|
|
|
|
|
bool allWrapped = true;
|
|
|
|
|
JS_SetCallHook(rt, nonStrictThisHook, (void *) &allWrapped);
|
|
|
|
|
EXEC("function nonstrict() { }\n"
|
|
|
|
|
"Boolean.prototype.nonstrict = nonstrict;\n"
|
|
|
|
|
"String.prototype.nonstrict = nonstrict;\n"
|
|
|
|
|
"Number.prototype.nonstrict = nonstrict;\n"
|
|
|
|
|
"Object.prototype.nonstrict = nonstrict;\n"
|
|
|
|
|
"nonstrict.call(true);\n"
|
|
|
|
|
"true.nonstrict();\n"
|
|
|
|
|
"nonstrict.call('');\n"
|
|
|
|
|
"''.nonstrict();\n"
|
|
|
|
|
"nonstrict.call(42);\n"
|
|
|
|
|
"(42).nonstrict();\n"
|
|
|
|
|
// The below don't really get 'wrapped', but it's okay.
|
|
|
|
|
"nonstrict.call(undefined);\n"
|
|
|
|
|
"nonstrict.call(null);\n"
|
|
|
|
|
"nonstrict.call({});\n"
|
|
|
|
|
"({}).nonstrict();\n");
|
|
|
|
|
CHECK(allWrapped);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
END_TEST(testDebugger_getThisNonStrict)
|
|
|
|
|
|
|
|
|
|
static void *
|
|
|
|
|
strictThisHook(JSContext *cx, JSStackFrame *fp, JSBool before, JSBool *ok, void *closure)
|
|
|
|
|
{
|
|
|
|
|
if (before) {
|
|
|
|
|
bool *anyWrapped = (bool *) closure;
|
|
|
|
|
jsval thisv;
|
|
|
|
|
JS_GetFrameThis(cx, fp, &thisv);
|
|
|
|
|
*anyWrapped = *anyWrapped || !JSVAL_IS_PRIMITIVE(thisv);
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BEGIN_TEST(testDebugger_getThisStrict)
|
|
|
|
|
{
|
|
|
|
|
bool anyWrapped = false;
|
|
|
|
|
JS_SetCallHook(rt, strictThisHook, (void *) &anyWrapped);
|
|
|
|
|
EXEC("function strict() { 'use strict'; }\n"
|
|
|
|
|
"Boolean.prototype.strict = strict;\n"
|
|
|
|
|
"String.prototype.strict = strict;\n"
|
|
|
|
|
"Number.prototype.strict = strict;\n"
|
|
|
|
|
"strict.call(true);\n"
|
|
|
|
|
"true.strict();\n"
|
|
|
|
|
"strict.call('');\n"
|
|
|
|
|
"''.strict();\n"
|
|
|
|
|
"strict.call(42);\n"
|
|
|
|
|
"(42).strict();\n"
|
|
|
|
|
"strict.call(undefined);\n"
|
|
|
|
|
"strict.call(null);\n");
|
|
|
|
|
CHECK(!anyWrapped);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
END_TEST(testDebugger_getThisStrict)
|