Bug 996881: Inherit 'use strict' directive when calling toSource/toString for asm.js modules; r=luke

--HG--
extra : rebase_source : 63ed080e38be66583c205d930b147bb1e2c66d2c
This commit is contained in:
Benjamin Bouvier 2014-04-17 14:06:50 +02:00
Родитель 19d8c91a10
Коммит 19f1372183
7 изменённых файлов: 84 добавлений и 12 удалений

Просмотреть файл

@ -237,6 +237,33 @@ if (isAsmJSCompilationAvailable() && isCachingEnabled()) {
})();
/* Implicit "use strict" context */
(function() {
var funcHeader = 'function (glob, ffi, heap) {',
funcBody = '\n"use asm";\n\
function g() {}\n\
return g;\n\n'
funcFooter = '}',
funcSource = funcHeader + funcBody + funcFooter
useStrict = '\n"use strict";\n';
var f4 = eval("\"use strict\";\n(" + funcSource + ")");
var expectedToString = funcHeader + useStrict + funcBody + funcFooter
var expectedToSource = '(' + expectedToString + ')'
assertEq(f4.toString(), expectedToString);
assertEq(f4.toSource(), expectedToSource);
if (isAsmJSCompilationAvailable() && isCachingEnabled()) {
var f5 = eval("\"use strict\";\n(" + funcSource + ")");
assertEq(isAsmJSModuleLoadedFromCache(f5), true);
assertEq(f5.toString(), expectedToString);
assertEq(f5.toSource(), expectedToSource);
}
})();
/* Functions */
(function() {

Просмотреть файл

@ -1143,7 +1143,13 @@ class MOZ_STACK_CLASS ModuleCompiler
uint32_t funcStart = parser_.pc->maybeFunction->pn_body->pn_pos.begin;
uint32_t offsetToEndOfUseAsm = parser_.tokenStream.currentToken().pos.end;
module_ = cx_->new_<AsmJSModule>(parser_.ss, funcStart, offsetToEndOfUseAsm);
// "use strict" should be added to the source if we are in an implicit
// strict context, see also comment above addUseStrict in
// js::FunctionToString.
bool strict = parser_.pc->sc->strict && !parser_.pc->sc->hasExplicitUseStrict();
module_ = cx_->new_<AsmJSModule>(parser_.ss, funcStart, offsetToEndOfUseAsm, strict);
if (!module_)
return false;
@ -1514,7 +1520,6 @@ class MOZ_STACK_CLASS ModuleCompiler
{
module_->initFuncEnd(parser_.tokenStream.currentToken().pos.end,
parser_.tokenStream.peekTokenPos().end);
masm_.finish();
if (masm_.oom())
return false;

Просмотреть файл

@ -800,8 +800,31 @@ js::AsmJSModuleToString(JSContext *cx, HandleFunction fun, bool addParenToLambda
if (!src)
return nullptr;
if (!out.append(src->chars(), src->length()))
return nullptr;
if (module.strict()) {
// We need to add "use strict" in the body right after the opening
// brace.
size_t bodyStart = 0, bodyEnd;
// No need to test for functions created with the Function ctor as
// these doesn't implicitly inherit the "use strict" context. Strict mode is
// enabled for functions created with the Function ctor only if they begin with
// the "use strict" directive, but these functions won't validate as asm.js
// modules.
ConstTwoByteChars chars(src->chars(), src->length());
if (!FindBody(cx, fun, chars, src->length(), &bodyStart, &bodyEnd))
return nullptr;
if (!out.append(chars, bodyStart) ||
!out.append("\n\"use strict\";\n") ||
!out.append(chars + bodyStart, src->length() - bodyStart))
{
return nullptr;
}
} else {
if (!out.append(src->chars(), src->length()))
return nullptr;
}
if (funCtor && !out.append("\n}"))
return nullptr;

Просмотреть файл

@ -328,7 +328,8 @@ AsmJSModule::staticallyLink(ExclusiveContext *cx)
}
}
AsmJSModule::AsmJSModule(ScriptSource *scriptSource, uint32_t funcStart, uint32_t offsetToEndOfUseAsm)
AsmJSModule::AsmJSModule(ScriptSource *scriptSource, uint32_t funcStart,
uint32_t offsetToEndOfUseAsm, bool strict)
: globalArgumentName_(nullptr),
importArgumentName_(nullptr),
bufferArgumentName_(nullptr),
@ -344,6 +345,7 @@ AsmJSModule::AsmJSModule(ScriptSource *scriptSource, uint32_t funcStart, uint32_
mozilla::PodZero(&pod);
scriptSource_->incref();
pod.minHeapLength_ = AsmJSAllocationGranularity;
pod.strict_ = strict;
}
AsmJSModule::~AsmJSModule()
@ -876,7 +878,7 @@ AsmJSModule::clone(JSContext *cx, ScopedJSDeletePtr<AsmJSModule> *moduleOut) con
{
AutoUnprotectCodeForClone cloneGuard(cx, *this);
*moduleOut = cx->new_<AsmJSModule>(scriptSource_, funcStart_, offsetToEndOfUseAsm_);
*moduleOut = cx->new_<AsmJSModule>(scriptSource_, funcStart_, offsetToEndOfUseAsm_, pod.strict_);
if (!*moduleOut)
return false;
@ -1313,8 +1315,9 @@ js::LookupAsmJSModuleInCache(ExclusiveContext *cx,
uint32_t funcStart = parser.pc->maybeFunction->pn_body->pn_pos.begin;
uint32_t offsetToEndOfUseAsm = parser.tokenStream.currentToken().pos.end;
bool strict = parser.pc->sc->strict && !parser.pc->sc->hasExplicitUseStrict();
ScopedJSDeletePtr<AsmJSModule> module(
cx->new_<AsmJSModule>(parser.ss, funcStart, offsetToEndOfUseAsm));
cx->new_<AsmJSModule>(parser.ss, funcStart, offsetToEndOfUseAsm, strict));
if (!module)
return false;
cursor = module->deserialize(cx, cursor);

Просмотреть файл

@ -431,6 +431,7 @@ class AsmJSModule
struct Pod {
uint32_t funcLength_;
uint32_t funcLengthWithRightBrace_;
bool strict_;
uint32_t numGlobalVars_;
uint32_t numFFIs_;
size_t funcPtrTableAndExitBytes_;
@ -464,7 +465,8 @@ class AsmJSModule
mutable bool codeIsProtected_;
public:
explicit AsmJSModule(ScriptSource *scriptSource, uint32_t functStart, uint32_t offsetToEndOfUseAsm);
explicit AsmJSModule(ScriptSource *scriptSource, uint32_t functStart,
uint32_t offsetToEndOfUseAsm, bool strict);
~AsmJSModule();
void trace(JSTracer *trc) {
@ -524,6 +526,9 @@ class AsmJSModule
uint32_t funcEndAfterCurly() const {
return funcStart_ + pod.funcLengthWithRightBrace_;
}
bool strict() const {
return pod.strict_;
}
bool addGlobalVarInit(const Value &v, AsmJSCoercion coercion, uint32_t *globalIndex) {
JS_ASSERT(pod.funcPtrTableAndExitBytes_ == 0);

Просмотреть файл

@ -626,14 +626,18 @@ const Class JSFunction::class_ = {
const Class* const js::FunctionClassPtr = &JSFunction::class_;
/* Find the body of a function (not including braces). */
static bool
FindBody(JSContext *cx, HandleFunction fun, ConstTwoByteChars chars, size_t length,
bool
js::FindBody(JSContext *cx, HandleFunction fun, ConstTwoByteChars chars, size_t length,
size_t *bodyStart, size_t *bodyEnd)
{
// We don't need principals, since those are only used for error reporting.
CompileOptions options(cx);
options.setFileAndLine("internal-findBody", 0)
.setVersion(fun->nonLazyScript()->getVersion());
options.setFileAndLine("internal-findBody", 0);
// For asm.js modules, there's no script.
if (fun->hasScript())
options.setVersion(fun->nonLazyScript()->getVersion());
AutoKeepAtoms keepAtoms(cx->perThreadData);
TokenStream ts(cx, options, chars.get(), length, nullptr);
int nest = 0;

Просмотреть файл

@ -554,6 +554,11 @@ CloneFunctionObject(JSContext *cx, HandleFunction fun, HandleObject parent,
gc::AllocKind kind = JSFunction::FinalizeKind,
NewObjectKind newKindArg = GenericObject);
extern bool
FindBody(JSContext *cx, HandleFunction fun, ConstTwoByteChars chars, size_t length,
size_t *bodyStart, size_t *bodyEnd);
} // namespace js
inline js::FunctionExtended *