We can use the script type to determine that instead. Script of type
TYPE_NATIVE are considered builtins, TYPE_NORMAL are not. The only exception
to this rule is the empty function, for which the script is TYPE_NATIVE
(observable by the debugger), but should be stringified to "function () {}"
instead of "function () { [native code] }". For this, I introduce a
hide_source flag on the script object.
We also use IsBuiltin and IsSubjectToDebugging interchangeably. For debugger,
we now use the latter, hiding the detail that only non-builtins are debuggable.
R=mstarzinger@chromium.org
Review URL: https://codereview.chromium.org/
1292283004
Cr-Commit-Position: refs/heads/master@{#30285}
Handle<Script> script = isolate->factory()->NewScript(source);
if (natives == NATIVES_CODE) {
script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
+ script->set_hide_source(true);
}
if (!script_name.is_null()) {
script->set_name(*script_name);
context_(function->context()),
seen_script_scope_(false),
failed_(false) {
- if (function->IsBuiltin()) context_ = Handle<Context>();
+ if (!function->IsSubjectToDebugging()) context_ = Handle<Context>();
}
Object* fun = it.frame()->function();
if (fun && fun->IsJSFunction()) {
// Don't stop in builtin functions.
- if (JSFunction::cast(fun)->IsBuiltin()) return;
+ if (!JSFunction::cast(fun)->IsSubjectToDebugging()) return;
GlobalObject* global = JSFunction::cast(fun)->context()->global_object();
// Don't stop in debugger functions.
if (IsDebugGlobal(global)) return;
}
// Skip all frames until we've seen the caller.
if (!(*seen_caller)) return false;
- // Also, skip non-visible built-in functions and any call with the builtins
- // object as receiver, so as to not reveal either the builtins object or
- // an internal function.
+ // Functions defined in native scripts are not visible unless directly
+ // exposed, in which case the native flag is set.
// The --builtins-in-stack-traces command line flag allows including
// internal call sites in the stack trace for debugging purposes.
if (!FLAG_builtins_in_stack_traces) {
if (receiver->IsJSBuiltinsObject()) return false;
- if (fun->IsBuiltin()) {
- return fun->shared()->native();
- } else if (!fun->IsSubjectToDebugging()) {
- return false;
- }
+ if (fun->IsBuiltin()) return fun->shared()->native();
}
return true;
}
set_flags(BooleanBit::set(flags(), kCompilationTypeBit,
type == COMPILATION_TYPE_EVAL));
}
+bool Script::hide_source() { return BooleanBit::get(flags(), kHideSourceBit); }
+void Script::set_hide_source(bool value) {
+ set_flags(BooleanBit::set(flags(), kHideSourceBit, value));
+}
Script::CompilationState Script::compilation_state() {
return BooleanBit::get(flags(), kCompilationStateBit) ?
COMPILATION_STATE_COMPILED : COMPILATION_STATE_INITIAL;
}
-bool SharedFunctionInfo::IsSubjectToDebugging() {
+bool SharedFunctionInfo::IsBuiltin() {
Object* script_obj = script();
- if (script_obj->IsUndefined()) return false;
+ if (script_obj->IsUndefined()) return true;
Script* script = Script::cast(script_obj);
Script::Type type = static_cast<Script::Type>(script->type()->value());
- return type == Script::TYPE_NORMAL;
+ return type != Script::TYPE_NORMAL;
}
-bool JSFunction::IsBuiltin() {
- return context()->global_object()->IsJSBuiltinsObject();
-}
+bool SharedFunctionInfo::IsSubjectToDebugging() { return !IsBuiltin(); }
+
+
+bool JSFunction::IsBuiltin() { return shared()->IsBuiltin(); }
bool JSFunction::IsSubjectToDebugging() {
inline CompilationState compilation_state();
inline void set_compilation_state(CompilationState state);
+ // [hide_source]: determines whether the script source can be exposed as
+ // function source. Encoded in the 'flags' field.
+ inline bool hide_source();
+ inline void set_hide_source(bool value);
+
// [origin_options]: optional attributes set by the embedder via ScriptOrigin,
// and used by the embedder to make decisions about the script. V8 just passes
// this through. Encoded in the 'flags' field.
// Bit positions in the flags field.
static const int kCompilationTypeBit = 0;
static const int kCompilationStateBit = 1;
- static const int kOriginOptionsShift = 2;
+ static const int kHideSourceBit = 2;
+ static const int kOriginOptionsShift = 3;
static const int kOriginOptionsSize = 3;
static const int kOriginOptionsMask = ((1 << kOriginOptionsSize) - 1)
<< kOriginOptionsShift;
// Tells whether this function should be subject to debugging.
inline bool IsSubjectToDebugging();
+ // Whether this function is defined in native code or extensions.
+ inline bool IsBuiltin();
+
// Check whether or not this function is inlineable.
bool IsInlineable();
// Get scope info and read from it for local variable information.
Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
+ RUNTIME_ASSERT(function->IsSubjectToDebugging());
Handle<SharedFunctionInfo> shared(function->shared());
Handle<ScopeInfo> scope_info(shared->scope_info());
DCHECK(*scope_info != ScopeInfo::Empty(isolate));
// THIS MUST BE DONE LAST SINCE WE MIGHT ADVANCE
// THE FRAME ITERATOR TO WRAP THE RECEIVER.
Handle<Object> receiver(it.frame()->receiver(), isolate);
- if (!receiver->IsJSObject() && is_sloppy(shared->language_mode()) &&
- !function->IsBuiltin()) {
+ DCHECK(!function->IsBuiltin());
+ if (!receiver->IsJSObject() && is_sloppy(shared->language_mode())) {
// If the receiver is not a JSObject and the function is not a
// builtin or strict-mode we have hit an optimization where a
// value object is not converted into a wrapped JS objects. To
// or not even a function.
return isolate->heap()->ToBoolean(
callback->IsJSFunction() &&
- (!JSFunction::cast(callback)->IsBuiltin() ||
+ (JSFunction::cast(callback)->IsSubjectToDebugging() ||
JSFunction::cast(callback)->shared()->bound()));
}
}
-RUNTIME_FUNCTION(Runtime_FunctionIsBuiltin) {
+RUNTIME_FUNCTION(Runtime_FunctionHidesSource) {
SealHandleScope shs(isolate);
DCHECK(args.length() == 1);
-
CONVERT_ARG_CHECKED(JSFunction, f, 0);
- return isolate->heap()->ToBoolean(f->IsBuiltin());
+
+ SharedFunctionInfo* shared = f->shared();
+ bool hide_source = !shared->script()->IsScript() ||
+ Script::cast(shared->script())->hide_source();
+ return isolate->heap()->ToBoolean(hide_source);
}
F(FunctionSetLength, 2, 1) \
F(FunctionSetPrototype, 2, 1) \
F(FunctionIsAPIFunction, 1, 1) \
- F(FunctionIsBuiltin, 1, 1) \
+ F(FunctionHidesSource, 1, 1) \
F(SetCode, 2, 1) \
F(SetNativeFlag, 1, 1) \
F(ThrowStrongModeTooFewArguments, 0, 1) \
throw MakeTypeError(kNotGeneric, 'Function.prototype.toString');
}
- if (%FunctionIsBuiltin(func)) {
+ if (%FunctionHidesSource(func)) {
return NativeCodeFunctionSourceString(func);
}