зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
19d8c91a10
Коммит
19f1372183
|
@ -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 *
|
||||
|
|
Загрузка…
Ссылка в новой задаче