JSString* js::AsmJSFunctionToString(JSContext* cx, HandleFunction fun) { AsmJSModule& module = FunctionToEnclosingModule(fun); const AsmJSModule::ExportedFunction& f = FunctionToExportedFunction(fun, module); uint32_t begin = module.srcStart() + f.startOffsetInModule(); uint32_t end = module.srcStart() + f.endOffsetInModule(); ScriptSource* source = module.scriptSource(); StringBuffer out(cx); if (!out.append("function ")) return nullptr; bool haveSource = source->hasSourceData(); if (!haveSource && !JSScript::loadSource(cx, source, &haveSource)) return nullptr; if (!haveSource) { // asm.js functions can't be anonymous MOZ_ASSERT(fun->atom()); if (!out.append(fun->atom())) return nullptr; if (!out.append("() {\n [sourceless code]\n}")) return nullptr; } else { // asm.js functions cannot have been created with a Function constructor // as they belong within a module. MOZ_ASSERT(!(begin == 0 && end == source->length() && source->argumentsNotIncluded())); if (module.strict()) { // AppendUseStrictSource expects its input to start right after the // function name, so split the source chars from the src into two parts: // the function name and the rest (arguments + body). // asm.js functions can't be anonymous MOZ_ASSERT(fun->atom()); if (!out.append(fun->atom())) return nullptr; size_t nameEnd = begin + fun->atom()->length(); Rooted<JSFlatString*> src(cx, source->substring(cx, nameEnd, end)); if (!AppendUseStrictSource(cx, fun, src, out)) return nullptr; } else { Rooted<JSFlatString*> src(cx, source->substring(cx, begin, end)); if (!src) return nullptr; if (!out.append(src)) return nullptr; } } return out.finishString(); }
JSString* js::AsmJSModuleToString(JSContext* cx, HandleFunction fun, bool addParenToLambda) { AsmJSModule& module = ModuleFunctionToModuleObject(fun).module(); uint32_t begin = module.srcStart(); uint32_t end = module.srcEndAfterCurly(); ScriptSource* source = module.scriptSource(); StringBuffer out(cx); if (addParenToLambda && fun->isLambda() && !out.append("(")) return nullptr; if (!out.append("function ")) return nullptr; if (fun->atom() && !out.append(fun->atom())) return nullptr; bool haveSource = source->hasSourceData(); if (!haveSource && !JSScript::loadSource(cx, source, &haveSource)) return nullptr; if (!haveSource) { if (!out.append("() {\n [sourceless code]\n}")) return nullptr; } else { // Whether the function has been created with a Function ctor bool funCtor = begin == 0 && end == source->length() && source->argumentsNotIncluded(); if (funCtor) { // Functions created with the function constructor don't have arguments in their source. if (!out.append("(")) return nullptr; if (PropertyName* argName = module.globalArgumentName()) { if (!out.append(argName)) return nullptr; } if (PropertyName* argName = module.importArgumentName()) { if (!out.append(", ") || !out.append(argName)) return nullptr; } if (PropertyName* argName = module.bufferArgumentName()) { if (!out.append(", ") || !out.append(argName)) return nullptr; } if (!out.append(") {\n")) return nullptr; } Rooted<JSFlatString*> src(cx, source->substring(cx, begin, end)); if (!src) return nullptr; if (module.strict()) { if (!AppendUseStrictSource(cx, fun, src, out)) return nullptr; } else { if (!out.append(src)) return nullptr; } if (funCtor && !out.append("\n}")) return nullptr; } if (addParenToLambda && fun->isLambda() && !out.append(")")) return nullptr; return out.finishString(); }