aboutsummaryrefslogtreecommitdiff
path: root/src/bun.js/bindings/CallSite.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/bun.js/bindings/CallSite.cpp')
-rw-r--r--src/bun.js/bindings/CallSite.cpp91
1 files changed, 91 insertions, 0 deletions
diff --git a/src/bun.js/bindings/CallSite.cpp b/src/bun.js/bindings/CallSite.cpp
new file mode 100644
index 000000000..522c6db1c
--- /dev/null
+++ b/src/bun.js/bindings/CallSite.cpp
@@ -0,0 +1,91 @@
+/**
+ * This source code is licensed under the terms found in the LICENSE file in
+ * node-jsc's root directory.
+ */
+
+#include "config.h"
+#include "CallSite.h"
+
+#include "helpers.h"
+
+#include <JavaScriptCore/JSCInlines.h>
+
+using namespace JSC;
+using namespace WebCore;
+
+namespace Zig {
+
+const JSC::ClassInfo CallSite::s_info = { "CallSite"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(CallSite) };
+
+void CallSite::finishCreation(VM& vm, JSC::JSGlobalObject* globalObject, JSCStackFrame& stackFrame, bool encounteredStrictFrame)
+{
+ Base::finishCreation(vm);
+
+ /* From v8's "Stack Trace API" (https://github.com/v8/v8/wiki/Stack-Trace-API):
+ * "To maintain restrictions imposed on strict mode functions, frames that have a
+ * strict mode function and all frames below (its caller etc.) are not allow to access
+ * their receiver and function objects. For those frames, getFunction() and getThis()
+ * will return undefined.".
+ * Thus, if we've already encountered a strict frame, we'll treat our frame as strict too. */
+
+ bool isStrictFrame = encounteredStrictFrame;
+ if (!isStrictFrame) {
+ JSC::CodeBlock* codeBlock = stackFrame.codeBlock();
+ if (codeBlock) {
+ isStrictFrame = codeBlock->ownerExecutable()->isInStrictContext();
+ }
+ }
+
+ JSC::JSObject* calleeObject = JSC::jsCast<JSC::JSObject*>(stackFrame.callee());
+
+ // Initialize "this" and "function" (and set the "IsStrict" flag if needed)
+ JSC::CallFrame* callFrame = stackFrame.callFrame();
+ if (isStrictFrame) {
+ m_thisValue.set(vm, this, JSC::jsUndefined());
+ m_function.set(vm, this, JSC::jsUndefined());
+ m_flags |= static_cast<unsigned int>(Flags::IsStrict);
+ } else {
+ if (callFrame) {
+ // We know that we're not in strict mode
+ m_thisValue.set(vm, this, callFrame->thisValue().toThis(globalObject, JSC::ECMAMode::sloppy()));
+ } else {
+ m_thisValue.set(vm, this, JSC::jsUndefined());
+ }
+
+ m_function.set(vm, this, stackFrame.callee());
+ }
+
+ m_functionName.set(vm, this, stackFrame.functionName());
+ m_sourceURL.set(vm, this, stackFrame.sourceURL());
+
+ const auto* sourcePositions = stackFrame.getSourcePositions();
+ if (sourcePositions) {
+ m_lineNumber = JSC::jsNumber(sourcePositions->line.oneBasedInt());
+ m_columnNumber = JSC::jsNumber(sourcePositions->startColumn.oneBasedInt());
+ }
+
+ if (stackFrame.isEval()) {
+ m_flags |= static_cast<unsigned int>(Flags::IsEval);
+ }
+ if (stackFrame.isConstructor()) {
+ m_flags |= static_cast<unsigned int>(Flags::IsConstructor);
+ }
+ if (!stackFrame.codeBlock()) {
+ m_flags |= static_cast<unsigned int>(Flags::IsNative);
+ }
+}
+
+template<typename Visitor>
+void CallSite::visitChildrenImpl(JSCell* cell, Visitor& visitor)
+{
+ CallSite* thisCallSite = jsCast<CallSite*>(cell);
+ Base::visitChildren(thisCallSite, visitor);
+ visitor.append(thisCallSite->m_thisValue);
+ visitor.append(thisCallSite->m_function);
+ visitor.append(thisCallSite->m_functionName);
+ visitor.append(thisCallSite->m_sourceURL);
+}
+
+DEFINE_VISIT_CHILDREN(CallSite);
+
+} \ No newline at end of file