summaryrefslogtreecommitdiff
path: root/js/src/jsfun.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jsfun.cpp')
-rw-r--r--js/src/jsfun.cpp92
1 files changed, 60 insertions, 32 deletions
diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp
index bcb0da80b2..be11bf4363 100644
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -815,8 +815,10 @@ CreateFunctionPrototype(JSContext* cx, JSProtoKey key)
RootedFunction functionProto(cx, &functionProto_->as<JSFunction>());
- const char* rawSource = "() {\n}";
+ const char* rawSource = "function () {\n}";
size_t sourceLen = strlen(rawSource);
+ size_t begin = 9;
+ MOZ_ASSERT(rawSource[begin] == '(');
mozilla::UniquePtr<char16_t[], JS::FreePolicy> source(InflateString(cx, rawSource, &sourceLen));
if (!source)
return nullptr;
@@ -838,8 +840,9 @@ CreateFunctionPrototype(JSContext* cx, JSProtoKey key)
RootedScript script(cx, JSScript::Create(cx,
options,
sourceObject,
- 0,
- ss->length()));
+ begin,
+ ss->length(),
+ 0));
if (!script || !JSScript::initFunctionPrototype(cx, script, functionProto))
return nullptr;
@@ -1019,53 +1022,62 @@ js::FunctionToString(JSContext* cx, HandleFunction fun, bool prettyPrint)
}
}
- if (fun->isAsync()) {
- if (!out.append("async "))
- return nullptr;
- }
-
- bool funIsMethodOrNonArrowLambda = (fun->isLambda() && !fun->isArrow()) || fun->isMethod() ||
- fun->isGetter() || fun->isSetter();
+ bool funIsNonArrowLambda = fun->isLambda() && !fun->isArrow();
bool haveSource = fun->isInterpreted() && !fun->isSelfHostedBuiltin();
- // If we're not in pretty mode, put parentheses around lambda functions and methods.
- if (haveSource && !prettyPrint && funIsMethodOrNonArrowLambda) {
+ // If we're not in pretty mode, put parentheses around lambda functions
+ // so that eval returns lambda, not function statement.
+ if (haveSource && !prettyPrint && funIsNonArrowLambda) {
if (!out.append("("))
return nullptr;
}
- if (!fun->isArrow()) {
- bool ok;
- if (fun->isStarGenerator() && !fun->isAsync())
- ok = out.append("function* ");
- else
- ok = out.append("function ");
- if (!ok)
- return nullptr;
- }
- if (fun->explicitName()) {
- if (!out.append(fun->explicitName()))
- return nullptr;
- }
if (haveSource && !script->scriptSource()->hasSourceData() &&
!JSScript::loadSource(cx, script->scriptSource(), &haveSource))
{
return nullptr;
}
+
+ auto AppendPrelude = [&out, &fun]() {
+ if (fun->isAsync()) {
+ if (!out.append("async "))
+ return false;
+ }
+
+ if (!fun->isArrow()) {
+ if (!out.append("function"))
+ return false;
+
+ if (fun->isStarGenerator()) {
+ if (!out.append('*'))
+ return false;
+ }
+ }
+
+ if (fun->explicitName()) {
+ if (!out.append(' '))
+ return false;
+ if (!out.append(fun->explicitName()))
+ return false;
+ }
+ return true;
+ };
+
if (haveSource) {
- Rooted<JSFlatString*> src(cx, script->sourceData(cx));
+ Rooted<JSFlatString*> src(cx, script->sourceDataWithPrelude(cx));
if (!src)
return nullptr;
if (!out.append(src))
return nullptr;
- if (!prettyPrint && funIsMethodOrNonArrowLambda) {
+ if (!prettyPrint && funIsNonArrowLambda) {
if (!out.append(")"))
return nullptr;
}
} else if (fun->isInterpreted() && !fun->isSelfHostedBuiltin()) {
- if (!out.append("() {\n ") ||
+ if (!AppendPrelude() ||
+ !out.append("() {\n ") ||
!out.append("[sourceless code]") ||
!out.append("\n}"))
{
@@ -1076,13 +1088,15 @@ js::FunctionToString(JSContext* cx, HandleFunction fun, bool prettyPrint)
bool derived = fun->infallibleIsDefaultClassConstructor(cx);
if (derived && fun->isDerivedClassConstructor()) {
- if (!out.append("(...args) {\n ") ||
+ if (!AppendPrelude() ||
+ !out.append("(...args) {\n ") ||
!out.append("super(...args);\n}"))
{
return nullptr;
}
} else {
- if (!out.append("() {\n "))
+ if (!AppendPrelude() ||
+ !out.append("() {\n "))
return nullptr;
if (!derived) {
@@ -1669,7 +1683,18 @@ FunctionConstructor(JSContext* cx, const CallArgs& args, GeneratorKind generator
StringBuffer sb(cx);
- if (!sb.append('('))
+ if (isAsync) {
+ if (!sb.append("async "))
+ return false;
+ }
+ if (!sb.append("function"))
+ return false;
+ if (isStarGenerator && !isAsync) {
+ if (!sb.append('*'))
+ return false;
+ }
+
+ if (!sb.append(" anonymous("))
return false;
if (args.length() > 1) {
@@ -1690,12 +1715,15 @@ FunctionConstructor(JSContext* cx, const CallArgs& args, GeneratorKind generator
if (i < args.length() - 2) {
// Step 9.d.iii.
- if (!sb.append(", "))
+ if (!sb.append(","))
return false;
}
}
}
+ if (!sb.append('\n'))
+ return false;
+
// Remember the position of ")".
Maybe<uint32_t> parameterListEnd = Some(uint32_t(sb.length()));
MOZ_ASSERT(FunctionConstructorMedialSigils[0] == ')');