зеркало из https://github.com/mozilla/gecko-dev.git
Bug 999790: Make asm.js modules and functions constructible; r=luke
--HG-- extra : rebase_source : b4d64db2b3faeb5aaac0d3f104de60b1c47f1fc2
This commit is contained in:
Родитель
f3f4985fe0
Коммит
35e35895f4
|
@ -0,0 +1,69 @@
|
|||
function CanBeConstructed(f) {
|
||||
var caught = false;
|
||||
try {
|
||||
new f;
|
||||
} catch (e) {
|
||||
caught = true;
|
||||
}
|
||||
return !caught;
|
||||
}
|
||||
|
||||
function IsConstructedFunction(f) {
|
||||
return f.hasOwnProperty('length')
|
||||
&& f.hasOwnProperty('name')
|
||||
&& f.hasOwnProperty('arguments')
|
||||
&& f.hasOwnProperty('caller')
|
||||
&& f.hasOwnProperty('prototype')
|
||||
&& f.prototype.hasOwnProperty('constructor')
|
||||
&& f.prototype.constructor === f;
|
||||
}
|
||||
|
||||
function IsntConstructedFunction(f) {
|
||||
return !f.hasOwnProperty('length')
|
||||
&& !f.hasOwnProperty('name')
|
||||
&& !f.hasOwnProperty('arguments')
|
||||
&& !f.hasOwnProperty('caller')
|
||||
&& !f.hasOwnProperty('prototype')
|
||||
}
|
||||
|
||||
var m = function() {
|
||||
"use asm"
|
||||
function g(){}
|
||||
return g;
|
||||
};
|
||||
assertEq(CanBeConstructed(m), true, "asm.js modules can't be constructed");
|
||||
|
||||
var objM = new m;
|
||||
assertEq(IsConstructedFunction(objM), true);
|
||||
|
||||
var g = m();
|
||||
assertEq(CanBeConstructed(g), true, "asm.js functions can't be constructed");
|
||||
// g is a ctor returning an primitive value, thus an empty object
|
||||
assertEq(Object.getOwnPropertyNames(new g).length, 0);
|
||||
|
||||
var n = function() {
|
||||
"use asm"
|
||||
function g(){return 42.0}
|
||||
function h(){return 42}
|
||||
return {
|
||||
g: g,
|
||||
h: h
|
||||
};
|
||||
};
|
||||
assertEq(CanBeConstructed(n), true, "asm.js modules can't be constructed");
|
||||
|
||||
var objN = new n;
|
||||
// objN is an object with attributes g and h
|
||||
assertEq(IsntConstructedFunction(objN), true);
|
||||
assertEq(objN.hasOwnProperty('g'), true);
|
||||
assertEq(objN.hasOwnProperty('h'), true);
|
||||
|
||||
assertEq(IsConstructedFunction(objN.g), true);
|
||||
assertEq(IsConstructedFunction(objN.h), true);
|
||||
|
||||
var h = n().h;
|
||||
assertEq(CanBeConstructed(h), true, "asm.js functions can't be constructed");
|
||||
// h is a ctor returning an primitive value, thus an empty object
|
||||
assertEq(Object.getOwnPropertyNames(new h).length, 0);
|
||||
|
||||
assertEq(typeof(function() {"use asm"; return {}}.prototype) !== 'undefined', true);
|
|
@ -515,6 +515,16 @@ CallAsmJS(JSContext *cx, unsigned argc, Value *vp)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (callArgs.isConstructing()) {
|
||||
// By spec, when a function is called as a constructor and this function
|
||||
// returns a primary type, which is the case for all asm.js exported
|
||||
// functions, the returned value is discarded and an empty object is
|
||||
// returned instead.
|
||||
JSObject *obj = NewBuiltinClassInstance(cx, &JSObject::class_);
|
||||
callArgs.rval().set(ObjectValue(*obj));
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (func.returnType()) {
|
||||
case AsmJSModule::Return_Void:
|
||||
callArgs.rval().set(UndefinedValue());
|
||||
|
@ -536,7 +546,7 @@ NewExportedFunction(JSContext *cx, const AsmJSModule::ExportedFunction &func,
|
|||
{
|
||||
RootedPropertyName name(cx, func.name());
|
||||
JSFunction *fun = NewFunction(cx, NullPtr(), CallAsmJS, func.numArgs(),
|
||||
JSFunction::NATIVE_FUN, cx->global(), name,
|
||||
JSFunction::ASMJS_CTOR, cx->global(), name,
|
||||
JSFunction::ExtendedFinalizeKind);
|
||||
if (!fun)
|
||||
return nullptr;
|
||||
|
@ -798,8 +808,8 @@ js::NewAsmJSModuleFunction(ExclusiveContext *cx, JSFunction *origFun, HandleObje
|
|||
{
|
||||
RootedPropertyName name(cx, origFun->name());
|
||||
|
||||
JSFunction::Flags flags = origFun->isLambda() ? JSFunction::NATIVE_LAMBDA_FUN
|
||||
: JSFunction::NATIVE_FUN;
|
||||
JSFunction::Flags flags = origFun->isLambda() ? JSFunction::ASMJS_LAMBDA_CTOR
|
||||
: JSFunction::ASMJS_CTOR;
|
||||
JSFunction *moduleFun = NewFunction(cx, NullPtr(), LinkAsmJS, origFun->nargs(),
|
||||
flags, NullPtr(), name,
|
||||
JSFunction::ExtendedFinalizeKind, TenuredObject);
|
||||
|
|
|
@ -193,7 +193,7 @@ ResolveInterpretedFunctionPrototype(JSContext *cx, HandleObject obj)
|
|||
{
|
||||
#ifdef DEBUG
|
||||
JSFunction *fun = &obj->as<JSFunction>();
|
||||
JS_ASSERT(fun->isInterpreted());
|
||||
JS_ASSERT(fun->isInterpreted() || fun->isAsmJSNative());
|
||||
JS_ASSERT(!fun->isFunctionPrototype());
|
||||
#endif
|
||||
|
||||
|
|
|
@ -46,13 +46,14 @@ class JSFunction : public JSObject
|
|||
SELF_HOSTED_CTOR = 0x0200, /* function is self-hosted builtin constructor and
|
||||
must be constructible but not decompilable. */
|
||||
HAS_REST = 0x0400, /* function has a rest (...) parameter */
|
||||
// 0x0800 is available
|
||||
ASMJS = 0x0800, /* function is an asm.js module or exported function */
|
||||
INTERPRETED_LAZY = 0x1000, /* function is interpreted but doesn't have a script yet */
|
||||
ARROW = 0x2000, /* ES6 '(args) => body' syntax */
|
||||
|
||||
/* Derived Flags values for convenience: */
|
||||
NATIVE_FUN = 0,
|
||||
NATIVE_LAMBDA_FUN = NATIVE_FUN | LAMBDA,
|
||||
ASMJS_CTOR = ASMJS | NATIVE_CTOR,
|
||||
ASMJS_LAMBDA_CTOR = ASMJS | NATIVE_CTOR | LAMBDA,
|
||||
INTERPRETED_LAMBDA = INTERPRETED | LAMBDA,
|
||||
INTERPRETED_LAMBDA_ARROW = INTERPRETED | LAMBDA | ARROW
|
||||
};
|
||||
|
@ -118,6 +119,7 @@ class JSFunction : public JSObject
|
|||
|
||||
/* Possible attributes of a native function: */
|
||||
bool isNativeConstructor() const { return flags() & NATIVE_CTOR; }
|
||||
bool isAsmJSNative() const { return flags() & ASMJS; }
|
||||
|
||||
/* Possible attributes of an interpreted function: */
|
||||
bool isFunctionPrototype() const { return flags() & IS_FUN_PROTO; }
|
||||
|
@ -147,7 +149,7 @@ class JSFunction : public JSObject
|
|||
|
||||
/* Compound attributes: */
|
||||
bool isBuiltin() const {
|
||||
return isNative() || isSelfHostedBuiltin();
|
||||
return (isNative() && !isAsmJSNative()) || isSelfHostedBuiltin();
|
||||
}
|
||||
bool isInterpretedConstructor() const {
|
||||
// Note: the JITs inline this check, so be careful when making changes
|
||||
|
|
Загрузка…
Ссылка в новой задаче