Bug 761723 - Save script sources to implement Function.prototype.toString. r=jorendorff,njn,jimb,jst,Ms2ger

--HG--
extra : rebase_source : de1b55647780a30f98fe84d29ee3cb4a437a3ece
This commit is contained in:
Benjamin Peterson 2012-07-20 20:17:38 +02:00
Родитель 2f82b105e6
Коммит 78a5439268
257 изменённых файлов: 1254 добавлений и 8212 удалений

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

@ -57,15 +57,15 @@ let inputValues = [
[false, "true", "true"],
// 11
[false, "document.getElementById", "function getElementById() {[native code]}",
[false, "document.getElementById", "function getElementById() {\n [native code]\n}",
"function getElementById() {\n [native code]\n}",
"function getElementById() {\n [native code]\n}",
"function getElementById() {[native code]}",
"document.wrappedJSObject.getElementById"],
// 12
[false, "(function() { return 42; })", "function () {return 42;}",
"function () {\n return 42;\n}",
"(function () {return 42;})"],
[false, "(function() { return 42; })", "function () { return 42; }",
"function () { return 42; }",
"(function () { return 42; })"],
// 13
[false, "new Date(" + dateNow + ")", (new Date(dateNow)).toString()],

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

@ -40,7 +40,7 @@ function runTests() {
root.setAttribute("onclick", listenerSource);
infos = els.getListenerInfoFor(root, {});
is(infos.length, 1, "Element should have listeners (1)");
is(infos[0].toSource(), 'function onclick(event) {' + listenerSource + '}',
is(infos[0].toSource(), 'function onclick(event) { ' + listenerSource + ' }',
"Unexpected serialization (1)");
is(infos[0].type, "click", "Wrong type (1)");
is(infos[0].capturing, false, "Wrong phase (1)");
@ -67,7 +67,7 @@ function runTests() {
root.addEventListener("foo", l, false, false);
infos = els.getListenerInfoFor(root, {});
is(infos.length, 2, "Element should have listeners (2)");
is(infos[0].toSource(), "(function (e) {alert(e);})",
is(infos[0].toSource(), "(function (e) { alert(e); })",
"Unexpected serialization (2)");
is(infos[0].type, "foo", "Wrong type (2)");
is(infos[0].capturing, true, "Wrong phase (2)");
@ -78,7 +78,7 @@ function runTests() {
is(jsdvalue.getWrappedValue(), l, "Wrong JS value! (1)");
*/
is(infos[1].toSource(), "(function (e) {alert(e);})",
is(infos[1].toSource(), "(function (e) { alert(e); })",
"Unexpected serialization (3)");
is(infos[1].type, "foo", "Wrong type (3)");
is(infos[1].capturing, false, "Wrong phase (3)");
@ -97,7 +97,7 @@ function runTests() {
root.onclick = l;
infos = els.getListenerInfoFor(root, {});
is(infos.length, 1, "Element should have listeners (3)");
is(infos[0].toSource(), '(function (e) {alert(e);})',
is(infos[0].toSource(), '(function (e) { alert(e); })',
"Unexpected serialization (4)");
is(infos[0].type, "click", "Wrong type (4)");
is(infos[0].capturing, false, "Wrong phase (4)");

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

@ -45,10 +45,10 @@ div.onload = f;
is(div.onload, f, "Should have 'f' as div's onload");
div.setAttribute("onload", "");
isnot(div.onload, f, "Should not longer have 'f' as div's onload");
is(div.onload.toString(), "function onload(event) {\n}",
is(div.onload.toString(), "function onload(event) { }",
"Should have wrapped empty string in a function");
div.setAttribute("onload", "foopy();");
is(div.onload.toString(), "function onload(event) {\n foopy();\n}",
is(div.onload.toString(), "function onload(event) { foopy(); }",
"Should have wrapped call in a function");
div.removeAttribute("onload");
is(div.onload, null, "Should have null onload now");
@ -69,11 +69,11 @@ function testPropagationToWindow(eventName) {
document.body.setAttribute("on"+eventName, eventName);
is(window["on"+eventName].toString(),
"function on"+eventName+"(event) {\n "+eventName+";\n}",
"function on"+eventName+"(event) { "+eventName+" }",
"Setting on"+eventName+"attribute on body should propagate to window");
document.createElement("body").setAttribute("on"+eventName, eventName+"2");
is(window["on"+eventName].toString(),
"function on"+eventName+"(event) {\n "+eventName+"2;\n}",
"function on"+eventName+"(event) { "+eventName+"2 }",
"Setting on"+eventName+"attribute on body outside the document should propagate to window");
}

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

@ -21,12 +21,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=689564
var div = document.createElement("div");
div.setAttribute("onclick", "div");
is(window.onclick, null, "div should not forward onclick");
is(div.onclick.toString(), "function onclick(event) {\n div;\n}",
is(div.onclick.toString(), "function onclick(event) { div }",
"div should have an onclick handler");
div.setAttribute("onscroll", "div");
is(window.onscroll, null, "div should not forward onscroll");
is(div.onscroll.toString(), "function onscroll(event) {\n div;\n}",
is(div.onscroll.toString(), "function onscroll(event) { div }",
"div should have an onscroll handler");
div.setAttribute("onpopstate", "div");
@ -36,25 +36,25 @@ is(div.onpopstate, null, "div should not have onpopstate handler");
var body = document.createElement("body");
body.setAttribute("onclick", "body");
is(window.onclick, null, "body should not forward onclick");
is(body.onclick.toString(), "function onclick(event) {\n body;\n}",
is(body.onclick.toString(), "function onclick(event) { body }",
"body should have an onclick handler");
body.setAttribute("onscroll", "body");
is(window.onscroll.toString(), "function onscroll(event) {\n body;\n}",
is(window.onscroll.toString(), "function onscroll(event) { body }",
"body should forward onscroll");
body.setAttribute("onpopstate", "body");
is(window.onpopstate.toString(), "function onpopstate(event) {\n body;\n}",
is(window.onpopstate.toString(), "function onpopstate(event) { body }",
"body should forward onpopstate");
var frameset = document.createElement("frameset");
frameset.setAttribute("onclick", "frameset");
is(window.onclick, null, "frameset should not forward onclick");
is(frameset.onclick.toString(), "function onclick(event) {\n frameset;\n}",
is(frameset.onclick.toString(), "function onclick(event) { frameset }",
"frameset should have an onclick handler");
frameset.setAttribute("onscroll", "frameset");
is(window.onscroll.toString(), "function onscroll(event) {\n frameset;\n}",
is(window.onscroll.toString(), "function onscroll(event) { frameset }",
"frameset should forward onscroll");
frameset.setAttribute("onpopstate", "frameset");
is(window.onpopstate.toString(), "function onpopstate(event) {\n frameset;\n}",
is(window.onpopstate.toString(), "function onpopstate(event) { frameset }",
"frameset should forward onpopstate");

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

@ -122,26 +122,13 @@ InterfaceObjectToString(JSContext* cx, unsigned argc, JS::Value *vp)
return false;
}
JS::Value* argv = JS_ARGV(cx, vp);
uint32_t indent = 0;
if (argc != 0 && !JS_ValueToECMAUint32(cx, argv[0], &indent))
return false;
nsAutoString spaces;
while (indent-- > 0) {
spaces.Append(PRUnichar(' '));
}
nsString str;
str.Append(spaces);
str.AppendLiteral("function ");
str.Append(name, length);
str.AppendLiteral("() {");
str.Append('\n');
str.Append(spaces);
str.AppendLiteral(" [native code]");
str.Append('\n');
str.Append(spaces);
str.AppendLiteral("}");
return xpc::NonVoidStringToJsval(cx, str, vp);

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

@ -8,15 +8,15 @@ var iframeScript = function() {
var ev = content.document.createEvent('HTMLEvents');
ev.initEvent('contextmenu', true, false);
element.dispatchEvent(ev);
}
};
XPCNativeWrapper.unwrap(content).ctxCallbackFired = function(data) {
sendAsyncMessage('test:callbackfired', {data: data});
}
};
XPCNativeWrapper.unwrap(content).onerror = function(e) {
sendAsyncMessage('test:errorTriggered', {data: e});
}
};
content.fireContextMenu(content.document.body);
content.fireContextMenu(content.document.getElementById('menu1-trigger'));

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

@ -1,13 +1,13 @@
{
"Should throw TypeError for function \"function () {\n localStorage.key();\n}\".": true,
"Should throw TypeError for function \"function () {\n localStorage.getItem();\n}\".": true,
"Should throw TypeError for function \"function () {\n localStorage.setItem();\n}\".": true,
"Should throw TypeError for function \"function () {\n localStorage.setItem(\"a\");\n}\".": true,
"Should throw TypeError for function \"function () {\n localStorage.removeItem();\n}\".": true,
"Should throw TypeError for function \"function () {\n sessionStorage.key();\n}\".": true,
"Should throw TypeError for function \"function () {\n sessionStorage.getItem();\n}\".": true,
"Should throw TypeError for function \"function () {\n sessionStorage.setItem();\n}\".": true,
"Should throw TypeError for function \"function () {\n sessionStorage.setItem(\"a\");\n}\".": true,
"Should throw TypeError for function \"function () {\n sessionStorage.removeItem();\n}\".": true,
"Should throw TypeError for function \"function () {\n new StorageEvent;\n}\".": true
"Should throw TypeError for function \"function () { localStorage.key(); }\".": true,
"Should throw TypeError for function \"function () { localStorage.getItem(); }\".": true,
"Should throw TypeError for function \"function () { localStorage.setItem(); }\".": true,
"Should throw TypeError for function \"function () { localStorage.setItem(\"a\"); }\".": true,
"Should throw TypeError for function \"function () { localStorage.removeItem(); }\".": true,
"Should throw TypeError for function \"function () { sessionStorage.key(); }\".": true,
"Should throw TypeError for function \"function () { sessionStorage.getItem(); }\".": true,
"Should throw TypeError for function \"function () { sessionStorage.setItem(); }\".": true,
"Should throw TypeError for function \"function () { sessionStorage.setItem(\"a\"); }\".": true,
"Should throw TypeError for function \"function () { sessionStorage.removeItem(); }\".": true,
"Should throw TypeError for function \"function () { new StorageEvent(); }\".": true
}

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

@ -18,8 +18,8 @@
// killed.
SimpleTest.requestLongerTimeout(100);
// Disable crash observers as it breaks later tests.
function iframeScriptFirst() {
// Disable this functionality, it breaks later tests.
SpecialPowers.prototype.registerProcessCrashObservers = function() { };
SpecialPowers.prototype.unregisterProcessCrashObservers = function() { };

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

@ -21,6 +21,33 @@
using namespace js;
using namespace js::frontend;
class AutoAttachToRuntime {
JSRuntime *rt;
public:
ScriptSource *ss;
AutoAttachToRuntime(JSRuntime *rt)
: rt(rt), ss(NULL) {}
~AutoAttachToRuntime() {
// This makes the source visible to the GC. If compilation fails, and no
// script refers to it, it will be collected.
if (ss)
ss->attachToRuntime(rt);
}
};
static bool
CheckLength(JSContext *cx, size_t length)
{
// Note this limit is simply so we can store sourceStart and sourceEnd in
// JSScript as 32-bits. It could be lifted fairly easily, since the compiler
// is using size_t internally already.
if (length > UINT32_MAX) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_SOURCE_TOO_LONG);
return false;
}
return true;
}
JSScript *
frontend::CompileScript(JSContext *cx, HandleObject scopeChain, StackFrame *callerFrame,
JSPrincipals *principals, JSPrincipals *originPrincipals,
@ -52,6 +79,15 @@ frontend::CompileScript(JSContext *cx, HandleObject scopeChain, StackFrame *call
JS_ASSERT_IF(callerFrame, compileAndGo);
JS_ASSERT_IF(staticLevel != 0, callerFrame);
if (!CheckLength(cx, length))
return NULL;
AutoAttachToRuntime attacher(cx->runtime);
SourceCompressionToken sct(cx->runtime);
ScriptSource *ss = ScriptSource::createFromSource(cx, chars, length, false, &sct);
if (!ss)
return NULL;
attacher.ss = ss;
Parser parser(cx, principals, originPrincipals, chars, length, filename, lineno, version,
/* foldConstants = */ true, compileAndGo);
if (!parser.init())
@ -72,7 +108,10 @@ frontend::CompileScript(JSContext *cx, HandleObject scopeChain, StackFrame *call
compileAndGo,
noScriptRval,
version,
staticLevel));
staticLevel,
ss,
0,
length));
if (!script)
return NULL;
@ -215,6 +254,15 @@ frontend::CompileFunctionBody(JSContext *cx, HandleFunction fun,
Bindings *bindings, const jschar *chars, size_t length,
const char *filename, unsigned lineno, JSVersion version)
{
if (!CheckLength(cx, length))
return false;
AutoAttachToRuntime attacher(cx->runtime);
SourceCompressionToken sct(cx->runtime);
ScriptSource *ss = ScriptSource::createFromSource(cx, chars, length, true, &sct);
if (!ss)
return NULL;
attacher.ss = ss;
Parser parser(cx, principals, originPrincipals, chars, length, filename, lineno, version,
/* foldConstants = */ true, /* compileAndGo = */ false);
if (!parser.init())
@ -239,7 +287,10 @@ frontend::CompileFunctionBody(JSContext *cx, HandleFunction fun,
/* compileAndGo = */ false,
/* noScriptRval = */ false,
version,
staticLevel));
staticLevel,
ss,
0,
length));
if (!script)
return false;

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

@ -4872,7 +4872,10 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
parent->compileAndGo,
/* noScriptRval = */ false,
parent->getVersion(),
parent->staticLevel + 1));
parent->staticLevel + 1,
bce->script->source,
funbox->bufStart,
funbox->bufEnd));
if (!script)
return false;

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

@ -1475,6 +1475,8 @@ struct FunctionBox : public ObjectBox
FunctionBox *kids;
FunctionBox *parent;
Bindings bindings; /* bindings for this function */
size_t bufStart;
size_t bufEnd;
uint16_t level;
uint16_t ndefaults;
StrictMode::StrictModeState strictModeState;

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

@ -177,6 +177,8 @@ FunctionBox::FunctionBox(ObjectBox* traceListHead, JSObject *obj, ParseNode *fn,
kids(NULL),
parent(tc->sc->inFunction() ? tc->sc->funbox() : NULL),
bindings(),
bufStart(0),
bufEnd(0),
level(tc->staticLevel),
ndefaults(0),
strictModeState(sms),
@ -1245,6 +1247,8 @@ Parser::functionArguments(ParseNode **listp, bool &hasRest)
return false;
}
tc->sc->funbox()->bufStart = tokenStream.offsetOfToken(tokenStream.currentToken());
hasRest = false;
ParseNode *argsbody = ListNode::create(PNK_ARGSBODY, this);
@ -1625,12 +1629,16 @@ Parser::functionDef(HandlePropertyName funName, FunctionType type, FunctionSynta
return NULL;
#if JS_HAS_EXPR_CLOSURES
if (bodyType == StatementListBody)
if (bodyType == StatementListBody) {
#endif
MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_BODY);
else if (kind == Statement && !MatchOrInsertSemicolon(context, &tokenStream))
return NULL;
#else
MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_BODY);
funbox->bufEnd = tokenStream.offsetOfToken(tokenStream.currentToken()) + 1;
#if JS_HAS_EXPR_CLOSURES
} else {
funbox->bufEnd = tokenStream.endOffset(tokenStream.currentToken());
if (kind == Statement && !MatchOrInsertSemicolon(context, &tokenStream))
return NULL;
}
#endif
pn->pn_pos.end = tokenStream.currentToken().pos.end;
@ -1743,6 +1751,7 @@ Parser::functionDef(HandlePropertyName funName, FunctionType type, FunctionSynta
ParseNode *
Parser::functionStmt()
{
JS_ASSERT(tokenStream.currentToken().type == TOK_FUNCTION);
RootedPropertyName name(context);
if (tokenStream.getToken(TSF_KEYWORD_IS_NAME) == TOK_NAME) {
name = tokenStream.currentToken().name();
@ -1764,6 +1773,7 @@ ParseNode *
Parser::functionExpr()
{
RootedPropertyName name(context);
JS_ASSERT(tokenStream.currentToken().type == TOK_FUNCTION);
if (tokenStream.getToken(TSF_KEYWORD_IS_NAME) == TOK_NAME)
name = tokenStream.currentToken().name();
else
@ -1889,6 +1899,7 @@ Parser::processDirectives(ParseNode *stmts)
if (isDirective) {
// It's a directive. Is it one we know?
if (atom == context->runtime->atomState.useStrictAtom && !gotStrictMode) {
tc->sc->setExplicitUseStrict();
if (!setStrictMode(true))
return false;
gotStrictMode = true;

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

@ -378,11 +378,11 @@ TokenStream::peekChars(int n, jschar *cp)
const jschar *
TokenStream::TokenBuf::findEOLMax(const jschar *p, size_t max)
{
JS_ASSERT(base <= p && p <= limit);
JS_ASSERT(base_ <= p && p <= limit_);
size_t n = 0;
while (true) {
if (p >= limit)
if (p >= limit_)
break;
if (n >= max)
break;
@ -1125,6 +1125,31 @@ TokenStream::matchUnicodeEscapeIdent(int32_t *cp)
return false;
}
size_t
TokenStream::endOffset(const Token &tok)
{
uint32_t lineno = tok.pos.begin.lineno;
JS_ASSERT(lineno <= tok.pos.end.lineno);
const jschar *end;
if (lineno < tok.pos.end.lineno) {
TokenBuf buf(tok.ptr, userbuf.addressOfNextRawChar() - userbuf.base());
for (; lineno < tok.pos.end.lineno; lineno++) {
jschar c;
do {
JS_ASSERT(buf.hasRawChars());
c = buf.getRawChar();
} while (!TokenBuf::isRawEOLChar(c));
if (c == '\r' && buf.hasRawChars())
buf.matchRawChar('\n');
}
end = buf.addressOfNextRawChar() + tok.pos.end.index;
} else {
end = tok.ptr + (tok.pos.end.index - tok.pos.begin.index);
}
JS_ASSERT(end <= userbuf.addressOfNextRawChar());
return end - userbuf.base();
}
/*
* Helper function which returns true if the first length(q) characters in p are
* the same as the characters in q.

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

@ -495,6 +495,9 @@ class TokenStream
TokenKind type = currentToken().type;
return type == type1 || type == type2;
}
size_t offsetOfToken(const Token &tok) const {
return tok.ptr - userbuf.base();
}
const CharBuffer &getTokenbuf() const { return tokenbuf; }
const char *getFilename() const { return filename; }
unsigned getLineno() const { return lineno; }
@ -668,6 +671,12 @@ class TokenStream
JS_ALWAYS_TRUE(matchToken(tt));
}
/*
* Return the offset into the source buffer of the end of the token.
*/
size_t endOffset(const Token &tok);
/*
* Give up responsibility for managing the sourceMap filename's memory.
*/
@ -704,14 +713,22 @@ class TokenStream
class TokenBuf {
public:
TokenBuf(const jschar *buf, size_t length)
: base(buf), limit(buf + length), ptr(buf) { }
: base_(buf), limit_(buf + length), ptr(buf) { }
bool hasRawChars() const {
return ptr < limit;
return ptr < limit_;
}
bool atStart() const {
return ptr == base;
return ptr == base_;
}
const jschar *base() const {
return base_;
}
const jschar *limit() const {
return limit_;
}
jschar getRawChar() {
@ -771,8 +788,8 @@ class TokenStream
const jschar *findEOLMax(const jschar *p, size_t max);
private:
const jschar *base; /* base of buffer */
const jschar *limit; /* limit for quick bounds check */
const jschar *base_; /* base of buffer */
const jschar *limit_; /* limit for quick bounds check */
const jschar *ptr; /* next char to get */
};

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

@ -28,6 +28,9 @@ class ContextFlags {
friend struct SharedContext;
friend struct FunctionBox;
// True if "use strict"; appears in the body instead of being inherited.
bool hasExplicitUseStrict:1;
// The (static) bindings of this script need to support dynamic name
// read/write access. Here, 'dynamic' means dynamic dictionary lookup on
// the scope chain for a dynamic set of keys. The primary examples are:
@ -106,7 +109,8 @@ class ContextFlags {
public:
ContextFlags(JSContext *cx)
: bindingsAccessedDynamically(false),
: hasExplicitUseStrict(false),
bindingsAccessedDynamically(false),
funIsHeavyweight(false),
funIsGenerator(false),
funMightAliasLocals(false),
@ -173,6 +177,7 @@ struct SharedContext {
// functions below.
#define INFUNC JS_ASSERT(inFunction())
bool hasExplicitUseStrict() const { return cxFlags.hasExplicitUseStrict; }
bool bindingsAccessedDynamically() const { return cxFlags.bindingsAccessedDynamically; }
bool funIsHeavyweight() const { INFUNC; return cxFlags.funIsHeavyweight; }
bool funIsGenerator() const { INFUNC; return cxFlags.funIsGenerator; }
@ -181,6 +186,7 @@ struct SharedContext {
bool funArgumentsHasLocalBinding() const { INFUNC; return cxFlags.funArgumentsHasLocalBinding; }
bool funDefinitelyNeedsArgsObj() const { INFUNC; return cxFlags.funDefinitelyNeedsArgsObj; }
void setExplicitUseStrict() { cxFlags.hasExplicitUseStrict = true; }
void setBindingsAccessedDynamically() { cxFlags.bindingsAccessedDynamically = true; }
void setFunIsHeavyweight() { cxFlags.funIsHeavyweight = true; }
void setFunIsGenerator() { INFUNC; cxFlags.funIsGenerator = true; }

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

@ -1,5 +1,5 @@
actual = '';
expected = 'function h(x, y) {\n return arguments;\n},2,4,8,';
expected = 'function h(x, y) { return arguments; },2,4,8,';
function h(x, y) { return arguments; }

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

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

@ -1,46 +0,0 @@
function f1(a=1) {}
assertEq(f1.toString(), "function f1(a = 1) {\n}");
function f2(a=1, b=2, c=3) {}
assertEq(f2.toString(), "function f2(a = 1, b = 2, c = 3) {\n}");
function f3(a, b, c=1, d=2) {}
assertEq(f3.toString(), "function f3(a, b, c = 1, d = 2) {\n}");
function f4(a, [b], c=1) {}
assertEq(f4.toString(), "function f4(a, [b], c = 1) {\n}");
function f5(a, b, c=1, ...rest) {}
assertEq(f5.toString(), "function f5(a, b, c = 1, ...rest) {\n}");
function f6(a, [b], c=1, ...rest) {}
assertEq(f6.toString(), "function f6(a, [b], c = 1, ...rest) {\n}");
function f7(a, c=d = 190) {}
assertEq(f7.toString(), "function f7(a, c = d = 190) {\n}");
function f8(a=(b = 8)) {
function nested() {
return a + b;
}
return nested;
}
assertEq(f8.toString(), "function f8(a = b = 8) {\n\n\
function nested() {\n\
return a + b;\n\
}\n\n\
return nested;\n\
}");
function f9(a, b, c={complexity : .5, is : 40 + great.prop}, d=[42], ...rest) {}
assertEq(f9.toString(), "function f9(a, b, c = {complexity: 0.5, is: 40 + great.prop}, d = [42], ...rest) {\n}");
function f10(a=12) { return arguments; }
assertEq(f10.toString(), "function f10(a = 12) {\n return arguments;\n}");
function f11(a=(0, c=1)) {}
assertEq(f11.length, 1);
var g = eval("(" + f11 + ")");
assertEq(g.length, 1);
function f12(a, b=4) {
return b;
function b() { }
}
assertEq(f12.toString(), "function f12(a, b = 4) {\n return b;\n\n function b() {\n }\n\n}");
function f13(a, b=4, ...rest) {
return b;
function b() { }
}
assertEq(f13.toString(), "function f13(a, b = 4, ...rest) {\n return b;\n\n function b() {\n }\n\n}");
function f14(x = let (y) 42, ...rest) {}
assertEq(f14.toString(), "function f14(x = let (y) 42, ...rest) {\n}");

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

@ -3,10 +3,8 @@ function no_defaults(a, ...rest) {
function rest() { return a; }
}
assertEq(typeof no_defaults(), "function");
assertEq(no_defaults.toString(), "function no_defaults(a, ...rest) {\n return rest;\n\n function rest() {\n return a;\n }\n\n}");
function with_defaults(a=42, ...rest) {
return rest;
function rest() { return a; }
}
assertEq(typeof with_defaults(), "function");
assertEq(with_defaults.toString(), "function with_defaults(a = 42, ...rest) {\n return rest;\n\n function rest() {\n return a;\n }\n\n}");

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

@ -1,2 +0,0 @@
g = (function (...rest) { return rest; });
assertEq(g.toString(), "function (...rest) {\n return rest;\n}");

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

@ -1,9 +0,0 @@
function test() {
3 && x++;
}
assertEq(test.toString(), "function test() {\n 3 && x++;\n}");
function f() {
a[1, 2]++;
}
assertEq(f.toString(), "function f() {\n a[1, 2]++;\n}");

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

@ -0,0 +1,6 @@
function example(a, b, c) {
var complicated = 3;
perform_some_operations();
}
var myfun = function (a, b) a + b;
assertEq(decompileThis(), snarf(thisFilename()));

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

@ -0,0 +1,18 @@
var f = Function("a", "b", "return a + b;");
assertEq(f.toString(), "function anonymous(a, b) { return a + b; }");
assertEq(f.toSource(), "(function anonymous(a, b) { return a + b; })");
assertEq(decompileFunction(f), f.toString());
assertEq(decompileBody(f), "return a + b;");
f = Function("a", "...rest", "return rest[42] + b;");
assertEq(f.toString(), "function anonymous(a, ...rest) { return rest[42] + b; }");
assertEq(f.toSource(), "(function anonymous(a, ...rest) { return rest[42] + b; })")
assertEq(decompileFunction(f), f.toString());
assertEq(decompileBody(f), "return rest[42] + b;");
f = Function("x", "return let (y) x;");
assertEq(f.toSource(), "(function anonymous(x) { return let (y) x; })");
f = Function("");
assertEq(f.toString(), "function anonymous() { }");
f = Function("", "(abc)");
assertEq(f.toString(), "function anonymous() { (abc) }");
f = Function("", "return function (a, b) a + b;")();
assertEq(f.toString(), "function (a, b) a + b");

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

@ -0,0 +1,32 @@
function f1(foo, bar) foo + bar;
assertEq(f1.toString(), "function f1(foo, bar) foo + bar");
assertEq(f1.toString(), f1.toSource());
assertEq(decompileFunction(f1), f1.toString());
assertEq(decompileBody(f1), "foo + bar;");
// No semicolon on purpose
function f2(foo, bar) foo + bar
assertEq(f2.toString(), "function f2(foo, bar) foo + bar");
assertEq(f2.toString(), f2.toSource());
var f3 = function (foo, bar) foo + bar;
assertEq(f3.toSource(), "(function (foo, bar) foo + bar)");
assertEq(f3.toString(), "function (foo, bar) foo + bar");
// No semicolon on purpose
var f4 = function (foo, bar) foo + bar
assertEq(f4.toSource(), "(function (foo, bar) foo + bar)");
assertEq(f4.toString(), "function (foo, bar) foo + bar");
var f5 = function (foo, bar) foo + bar ;
assertEq(f5.toSource(), "(function (foo, bar) foo + bar)");
assertEq(f5.toString(), "function (foo, bar) foo + bar");
var f6 = function (foo, bar) foo + bar; var a = 42
assertEq(f6.toSource(), "(function (foo, bar) foo + bar)");
assertEq(f6.toString(), "function (foo, bar) foo + bar");
var f7 = function (foo, bar) foo + bar + '\
long\
string\
test\
'
// a comment followed by some space
assertEq(f7.toString(), "function (foo, bar) foo + bar + '\\\nlong\\\nstring\\\ntest\\\n'");
assertEq(f7.toSource(), "(" + f7.toString() + ")");

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

@ -0,0 +1,2 @@
assertEq(Function.prototype.toString(), "function () {\n}");
assertEq(Function.prototype.toSource(), "function () {\n}");

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

@ -0,0 +1,7 @@
var o = {get prop() a + b, set prop(x) a + b};
var prop = Object.getOwnPropertyDescriptor(o, "prop");
assertEq(prop.get.toString(), "function () a + b");
assertEq(prop.get.toSource(), "(function () a + b)");
assertEq(prop.set.toString(), "function (x) a + b");
assertEq(prop.set.toSource(), "(function (x) a + b)");
assertEq(o.toSource(), "({get prop () a + b, set prop (x) a + b})");

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

@ -0,0 +1,15 @@
var f1 = function f0(a, b) { return a + b; }
assertEq(f1.toSource(), "(function f0(a, b) { return a + b; })");
assertEq(f1.toString(), "function f0(a, b) { return a + b; }");
assertEq(decompileFunction(f1), f1.toString());
assertEq(decompileBody(f1), "return a + b;");
var f2 = function (a, b) { return a + b; };
assertEq(f2.toSource(), "(function (a, b) { return a + b; })");
assertEq(f2.toString(), "function (a, b) { return a + b; }");
assertEq(decompileFunction(f2), f2.toString());
assertEq(decompileBody(f2), "return a + b;");
var f3 = (function (a, b) { return a + b; });
assertEq(f3.toSource(), "(function (a, b) { return a + b; })");
assertEq(f3.toString(), "function (a, b) { return a + b; }");
assertEq(decompileFunction(f3), f3.toString());
assertEq(decompileBody(f3), "return a + b;");

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

@ -0,0 +1,10 @@
function f1(a, b) {
return a + b;
}
assertEq(f1.toString(), "function f1(a, b) {\n return a + b;\n}");
assertEq(f1.toSource(), f1.toString());
function f2(a, /* ))))pernicious comment */ b,
c, // another comment((
d) {}
assertEq(f2.toString(), "function f2(a, /* ))))pernicious comment */ b,\n c, // another comment((\n d) {}");
assertEq(decompileBody(f2), "");

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

@ -0,0 +1,12 @@
function outer() {
"use strict";
function inner() {}
return inner;
}
assertEq(outer().toString().indexOf("use strict") != -1, true);
function outer2() {
"use strict";
function inner() blah;
return inner;
}
assertEq(outer2().toString().indexOf("/* use strict */") != -1, true);

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

@ -8,7 +8,7 @@ function test(str, arg, result)
var fun = new Function('x', str);
var got = fun.toSource().replace(/\n/g,'');
var expect = '(function anonymous(x) {' + str + '})';
var expect = '(function anonymous(x) { ' + str + ' })';
if (got !== expect) {
print("GOT: " + got);
print("EXPECT: " + expect);
@ -341,20 +341,3 @@ test('switch (x) {case 3:let y;return 3;case 4:let z;return 4;default:return x;}
test('switch (x) {case 3:let x;break;default:if (x === undefined) {return "ponies";}}');
test('switch (x) {case 3:default:let y;let (y = x) {return y;}}');
isError('switch (x) {case 3:let y;return 3;case 4:let y;return 4;default:;}');
// test weird cases where the decompiler changes tokens
function testWeird(str, printedAs, arg, result)
{
var fun = new Function('x', str);
// this is lame and doesn't normalize whitespace so if an assert fails
// here, see if its just whitespace and fix the caller
assertEq(fun.toSource(), '(function anonymous(x) {' + printedAs + '})');
test(printedAs, arg, result);
}
testWeird('let y = x;return x;', 'var y = x;return x;');
testWeird('let y = 1, y = x;return y;', 'var y = 1, y = x;return y;');
testWeird('return let ({x:x, y:y} = x) x + y', 'return let ({x, y} = x) x + y;', {x:'pon', y:'ies'});
testWeird('let ({x:x, y:y} = x) {return x + y;}', 'let ({x, y} = x) {return x + y;}', {x:'pon', y:'ies'});

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

@ -0,0 +1,7 @@
var g = newGlobal('new-compartment');
var dbg = Debugger(g);
dbg.onNewScript = function (s) {
eval(longScript);
}
const longScript = "var x = 1;\n" + new Array(5000).join("x + ") + "x";
g.eval(longScript);

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

@ -116,7 +116,7 @@ MSG_DEF(JSMSG_UNMATCHED_RIGHT_PAREN, 62, 0, JSEXN_SYNTAXERR, "unmatched ) in r
MSG_DEF(JSMSG_TOO_BIG_TO_ENCODE, 63, 0, JSEXN_INTERNALERR, "data are to big to encode")
MSG_DEF(JSMSG_ARG_INDEX_OUT_OF_RANGE, 64, 1, JSEXN_RANGEERR, "argument {0} accesses an index that is out of range")
MSG_DEF(JSMSG_SPREAD_TOO_LARGE, 65, 0, JSEXN_RANGEERR, "array too large due to spread operand(s)")
MSG_DEF(JSMSG_UNUSED66, 66, 0, JSEXN_NONE, "")
MSG_DEF(JSMSG_SOURCE_TOO_LONG, 66, 0, JSEXN_RANGEERR, "source is too long")
MSG_DEF(JSMSG_UNUSED67, 67, 0, JSEXN_NONE, "")
MSG_DEF(JSMSG_BAD_SCRIPT_MAGIC, 68, 0, JSEXN_INTERNALERR, "bad script XDR magic number")
MSG_DEF(JSMSG_PAREN_BEFORE_FORMAL, 69, 0, JSEXN_SYNTAXERR, "missing ( before formal parameters")

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

@ -230,3 +230,26 @@ BEGIN_TEST(testXDR_bug516827)
return true;
}
END_TEST(testXDR_bug516827)
BEGIN_TEST(testXDR_source)
{
const char *samples[] = {
// This can't possibly fail to compress well, can it?
"function f(x) { return x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x }",
"short",
NULL
};
for (const char **s = samples; *s; s++) {
JSScript *script = JS_CompileScript(cx, global, *s, strlen(*s), __FILE__, __LINE__);
CHECK(script);
script = FreezeThaw(cx, script);
CHECK(script);
JSString *out = JS_DecompileScript(cx, script, "testing", 0);
CHECK(out);
JSBool equal;
CHECK(JS_StringEqualsAscii(cx, out, *s, &equal));
CHECK(equal);
}
return true;
}
END_TEST(testXDR_source)

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

@ -810,6 +810,9 @@ JSRuntime::JSRuntime()
data(NULL),
gcLock(NULL),
gcHelperThread(thisFromCtor()),
#ifdef JS_THREADSAFE
sourceCompressorThread(thisFromCtor()),
#endif
defaultFreeOp_(thisFromCtor(), false, false),
debuggerMutations(0),
securityCallbacks(const_cast<JSSecurityCallbacks *>(&NullSecurityCallbacks)),
@ -829,6 +832,7 @@ JSRuntime::JSRuntime()
sameCompartmentWrapObjectCallback(NULL),
preWrapObjectCallback(NULL),
preserveWrapperCallback(NULL),
scriptSources(NULL),
#ifdef DEBUG
noGCOrAllocationCheck(0),
#endif
@ -894,6 +898,11 @@ JSRuntime::init(uint32_t maxbytes)
if (!scriptFilenameTable.init())
return false;
#ifdef JS_THREADSAFE
if (!sourceCompressorThread.init())
return false;
#endif
if (!evalCache.init())
return false;
@ -919,6 +928,10 @@ JSRuntime::~JSRuntime()
*/
FreeScriptFilenames(this);
#ifdef JS_THREADSAFE
sourceCompressorThread.finish();
#endif
#ifdef DEBUG
/* Don't hurt everyone in leaky ol' Mozilla with a fatal JS_ASSERT! */
if (!JS_CLIST_IS_EMPTY(&contextList)) {
@ -5324,27 +5337,12 @@ JS_PUBLIC_API(JSString *)
JS_DecompileScript(JSContext *cx, JSScript *script, const char *name, unsigned indent)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
JSPrinter *jp;
JSString *str;
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
#ifdef DEBUG
if (cx->compartment != script->compartment())
CompartmentChecker::fail(cx->compartment, script->compartment());
#endif
jp = js_NewPrinter(cx, name, NULL,
indent & ~JS_DONT_PRETTY_PRINT,
!(indent & JS_DONT_PRETTY_PRINT),
false, false);
if (!jp)
return NULL;
if (js_DecompileScript(jp, script))
str = js_GetPrinterOutput(jp);
else
str = NULL;
js_DestroyPrinter(jp);
return str;
if (script->function())
return JS_DecompileFunction(cx, script->function(), indent);
return script->sourceData(cx);
}
JS_PUBLIC_API(JSString *)
@ -5354,10 +5352,7 @@ JS_DecompileFunction(JSContext *cx, JSFunction *fun, unsigned indent)
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
assertSameCompartment(cx, fun);
return js_DecompileToString(cx, "JS_DecompileFunction", fun,
indent & ~JS_DONT_PRETTY_PRINT,
!(indent & JS_DONT_PRETTY_PRINT),
false, false, js_DecompileFunction);
return fun->toString(cx, false, !(indent & JS_DONT_PRETTY_PRINT));
}
JS_PUBLIC_API(JSString *)
@ -5367,10 +5362,7 @@ JS_DecompileFunctionBody(JSContext *cx, JSFunction *fun, unsigned indent)
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
assertSameCompartment(cx, fun);
return js_DecompileToString(cx, "JS_DecompileFunctionBody", fun,
indent & ~JS_DONT_PRETTY_PRINT,
!(indent & JS_DONT_PRETTY_PRINT),
false, false, js_DecompileFunctionBody);
return fun->toString(cx, true, !(indent & JS_DONT_PRETTY_PRINT));
}
JS_NEVER_INLINE JS_PUBLIC_API(JSBool)

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

@ -159,18 +159,18 @@ struct ConservativeGCData
}
};
class ToSourceCache
class SourceDataCache
{
typedef HashMap<JSFunction *,
JSString *,
DefaultHasher<JSFunction *>,
typedef HashMap<ScriptSource *,
JSFixedString *,
DefaultHasher<ScriptSource *>,
SystemAllocPolicy> Map;
Map *map_;
public:
ToSourceCache() : map_(NULL) {}
JSString *lookup(JSFunction *fun);
void put(JSFunction *fun, JSString *);
void purge();
Map *map_;
public:
SourceDataCache() : map_(NULL) {}
JSFixedString *lookup(ScriptSource *ss);
void put(ScriptSource *ss, JSFixedString *);
void purge();
};
struct EvalCacheLookup
@ -751,6 +751,10 @@ struct JSRuntime : js::RuntimeFriendFields
js::GCHelperThread gcHelperThread;
#ifdef JS_THREADSAFE
js::SourceCompressorThread sourceCompressorThread;
#endif
private:
js::FreeOp defaultFreeOp_;
@ -800,7 +804,7 @@ struct JSRuntime : js::RuntimeFriendFields
js::PropertyCache propertyCache;
js::NewObjectCache newObjectCache;
js::NativeIterCache nativeIterCache;
js::ToSourceCache toSourceCache;
js::SourceDataCache sourceDataCache;
js::EvalCache evalCache;
/* State used by jsdtoa.cpp. */
@ -830,6 +834,8 @@ struct JSRuntime : js::RuntimeFriendFields
js::ScriptFilenameTable scriptFilenameTable;
js::ScriptSource *scriptSources;
#ifdef DEBUG
size_t noGCOrAllocationCheck;
#endif

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

@ -10,6 +10,7 @@
*/
#include <string.h>
#include "mozilla/RangedPtr.h"
#include "mozilla/Util.h"
#include "jstypes.h"
@ -40,6 +41,7 @@
#include "gc/Marking.h"
#include "vm/Debugger.h"
#include "vm/ScopeObject.h"
#include "vm/StringBuffer.h"
#include "vm/Xdr.h"
#ifdef JS_METHODJIT
@ -521,34 +523,177 @@ JS_FRIEND_DATA(Class) js::FunctionClass = {
fun_trace
};
JSString *
ToSourceCache::lookup(JSFunction *fun)
{
if (!map_)
return NULL;
if (Map::Ptr p = map_->lookup(fun))
return p->value;
return NULL;
}
void
ToSourceCache::put(JSFunction *fun, JSString *str)
/* Find the body of a function (not including braces). */
static bool
FindBody(JSContext *cx, JSFunction *fun, const jschar *chars, size_t length,
size_t *bodyStart, size_t *bodyEnd)
{
if (!map_) {
map_ = OffTheBooks::new_<Map>();
if (!map_)
return;
map_->init();
// We don't need principals, since those are only used for error reporting.
TokenStream ts(cx, NULL, NULL, chars, length, "internal-FindBody", 0,
fun->script()->getVersion(), NULL);
JS_ASSERT(chars[0] == '(');
int nest = 0;
bool onward = true;
// Skip arguments list.
do {
switch (ts.getToken()) {
case TOK_LP:
nest++;
break;
case TOK_RP:
if (--nest == 0)
onward = false;
break;
case TOK_ERROR:
// Must be memory.
return false;
default:
break;
}
} while (onward);
DebugOnly<bool> braced = ts.matchToken(TOK_LC);
if (ts.getToken() == TOK_ERROR)
return false;
JS_ASSERT(!!(fun->flags & JSFUN_EXPR_CLOSURE) ^ braced);
*bodyStart = ts.offsetOfToken(ts.currentToken());
RangedPtr<const jschar> p(chars, length);
p = chars + length;
for (; unicode::IsSpaceOrBOM2(p[-1]); p--)
;
if (p[-1] == '}') {
p--;
for (; unicode::IsSpaceOrBOM2(p[-1]); p--)
;
} else {
JS_ASSERT(!braced);
}
(void) map_->put(fun, str);
*bodyEnd = p.get() - chars;
return true;
}
void
ToSourceCache::purge()
JSString *
JSFunction::toString(JSContext *cx, bool bodyOnly, bool lambdaParen)
{
Foreground::delete_(map_);
map_ = NULL;
StringBuffer out(cx);
if (!bodyOnly) {
// If we're not in pretty mode, put parentheses around lambda functions.
if (isInterpreted() && !lambdaParen && (flags & JSFUN_LAMBDA)) {
if (!out.append("("))
return NULL;
}
if (!out.append("function "))
return NULL;
if (atom) {
if (!out.append(atom))
return NULL;
}
}
if (isInterpreted()) {
RootedString src(cx, script()->sourceData(cx));
if (!src)
return NULL;
const jschar *chars = src->getChars(cx);
if (!chars)
return NULL;
bool exprBody = flags & JSFUN_EXPR_CLOSURE;
// The source data for functions created by calling the Function
// constructor is only the function's body.
bool funCon = script()->sourceStart == 0 && script()->source->argumentsNotIncluded();
// Functions created with the constructor should not be using the
// expression body extension.
JS_ASSERT_IF(funCon, !exprBody);
JS_ASSERT_IF(!funCon, src->length() > 0 && chars[0] == '(');
// If a function inherits strict mode by having scopes above it that
// have "use strict", we insert "use strict" into the body of the
// function. This ensures that if the result of toString is evaled, the
// resulting function will have the same semantics.
bool addUseStrict = script()->strictModeCode && !script()->explicitUseStrict;
// Functions created with the constructor can't have inherited strict
// mode.
JS_ASSERT(!funCon || !addUseStrict);
bool buildBody = funCon && !bodyOnly;
if (buildBody) {
// This function was created with the Function constructor. We don't
// have source for the arguments, so we have to generate that. Part
// of bug 755821 should be cobbling the arguments passed into the
// Function constructor into the source string.
if (!out.append("("))
return NULL;
// Fish out the argument names.
BindingVector *localNames = cx->new_<BindingVector>(cx);
js::ScopedDeletePtr<BindingVector> freeNames(localNames);
if (!GetOrderedBindings(cx, script()->bindings, localNames))
return NULL;
for (unsigned i = 0; i < nargs; i++) {
if ((i && !out.append(", ")) ||
(i == unsigned(nargs - 1) && hasRest() && !out.append("...")) ||
!out.append((*localNames)[i].maybeName)) {
return NULL;
}
}
if (!out.append(") { "))
return NULL;
}
if ((bodyOnly && !funCon) || addUseStrict) {
// We need to get at the body either because we're only supposed to
// return the body or we need to insert "use strict" into the body.
JS_ASSERT(!buildBody);
size_t bodyStart = 0, bodyEnd = 0;
if (!FindBody(cx, this, chars, src->length(), &bodyStart, &bodyEnd))
return NULL;
if (addUseStrict) {
// Output source up to beginning of body.
if (!out.append(chars, bodyStart))
return NULL;
if (exprBody) {
// We can't insert a statement into a function with an
// expression body. Do what the decompiler did, and insert a
// comment.
if (!out.append("/* use strict */ "))
return NULL;
} else {
if (!out.append("\"use strict\";\n"))
return NULL;
}
}
// Output just the body (for bodyOnly) or the body and possibly
// closing braces (for addUseStrict).
size_t dependentEnd = (bodyOnly) ? bodyEnd : src->length();
if (!out.append(chars + bodyStart, dependentEnd - bodyStart))
return NULL;
} else {
if (!out.append(src))
return NULL;
}
if (buildBody) {
if (!out.append(" }"))
return NULL;
}
if (bodyOnly) {
// Slap a semicolon on the end of functions with an expression body.
if (exprBody && !out.append(";"))
return NULL;
} else if (!lambdaParen && (flags & JSFUN_LAMBDA)) {
if (!out.append(")"))
return NULL;
}
} else {
JS_ASSERT(!(flags & JSFUN_EXPR_CLOSURE));
if ((!bodyOnly && !out.append("() {\n ")) ||
!out.append("[native code]") ||
(!bodyOnly && !out.append("\n}")))
return NULL;
}
return out.finishString();
}
JSString *
@ -568,19 +713,7 @@ fun_toStringHelper(JSContext *cx, JSObject *obj, unsigned indent)
if (!fun)
return NULL;
if (!indent) {
if (JSString *str = cx->runtime->toSourceCache.lookup(fun))
return str;
}
JSString *str = JS_DecompileFunction(cx, fun, indent);
if (!str)
return NULL;
if (!indent)
cx->runtime->toSourceCache.put(fun, str);
return str;
return fun->toString(cx, false, indent != JS_DONT_PRETTY_PRINT);
}
static JSBool

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

@ -153,6 +153,8 @@ struct JSFunction : public JSObject
inline const js::Value &getBoundFunctionArgument(unsigned which) const;
inline size_t getBoundFunctionArgumentCount() const;
JSString *toString(JSContext *cx, bool bodyOnly, bool pretty);
private:
inline js::FunctionExtended *toExtended();
inline const js::FunctionExtended *toExtended() const;

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

@ -3082,7 +3082,7 @@ PurgeRuntime(JSTracer *trc)
rt->propertyCache.purge(rt);
rt->newObjectCache.purge();
rt->nativeIterCache.purge();
rt->toSourceCache.purge();
rt->sourceDataCache.purge();
rt->evalCache.clear();
for (ContextIter acx(rt); !acx.done(); acx.next())
@ -3487,8 +3487,10 @@ SweepPhase(JSRuntime *rt, JSGCInvocationKind gckind, bool *startBackgroundSweep)
* script and calls rt->destroyScriptHook, the hook can still access the
* script's filename. See bug 323267.
*/
if (rt->gcIsFull)
if (rt->gcIsFull) {
SweepScriptFilenames(rt);
ScriptSource::sweep(rt);
}
/*
* This removes compartments from rt->compartment, so we do it last to make

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

@ -356,7 +356,10 @@ js::XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enc
NeedsArgsObj,
OwnFilename,
ParentFilename,
IsGenerator
IsGenerator,
OwnSource,
ParentSource,
ExplicitUseStrict
};
uint32_t length, lineno, nslots;
@ -500,6 +503,8 @@ js::XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enc
scriptBits |= (1 << SavedCallerFun);
if (script->strictModeCode)
scriptBits |= (1 << StrictModeCode);
if (script->explicitUseStrict)
scriptBits |= (1 << ExplicitUseStrict);
if (script->bindingsAccessedDynamically)
scriptBits |= (1 << ContainsDynamicNameAccess);
if (script->funHasExtensibleScope)
@ -513,6 +518,9 @@ js::XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enc
? (1 << ParentFilename)
: (1 << OwnFilename);
}
scriptBits |= (enclosingScript && enclosingScript->source == script->source)
? (1 << ParentSource)
: (1 << OwnSource);
if (script->isGenerator)
scriptBits |= (1 << IsGenerator);
@ -565,7 +573,8 @@ js::XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enc
/* compileAndGo = */ false,
!!(scriptBits & (1 << NoScriptRval)),
version_,
/* staticLevel = */ 0);
/* staticLevel = */ 0,
NULL, 0, 0);
if (!script || !JSScript::partiallyInit(cx, script,
length, nsrcnotes, natoms, nobjects,
nregexps, ntrynotes, nconsts, nClosedArgs,
@ -583,6 +592,8 @@ js::XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enc
if (scriptBits & (1 << StrictModeCode))
script->strictModeCode = true;
if (scriptBits & (1 << ExplicitUseStrict))
script->explicitUseStrict = true;
if (scriptBits & (1 << ContainsDynamicNameAccess))
script->bindingsAccessedDynamically = true;
if (scriptBits & (1 << FunHasExtensibleScope))
@ -621,6 +632,19 @@ js::XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enc
script->filename = enclosingScript->filename;
}
if (scriptBits & (1 << OwnSource)) {
if (!ScriptSource::performXDR<mode>(xdr, &script->source))
return false;
} else if (scriptBits & (1 << ParentSource)) {
JS_ASSERT(enclosingScript);
if (mode == XDR_DECODE)
script->source = enclosingScript->source;
}
if (!xdr->codeUint32(&script->sourceStart))
return false;
if (!xdr->codeUint32(&script->sourceEnd))
return false;
if (mode == XDR_DECODE) {
script->lineno = lineno;
script->nslots = uint16_t(nslots);
@ -932,6 +956,373 @@ JSScript::destroySourceMap(FreeOp *fop)
fop->free_(releaseSourceMap());
}
#ifdef JS_THREADSAFE
void
SourceCompressorThread::compressorThread(void *arg)
{
PR_SetCurrentThreadName("JS Source Compressing Thread");
static_cast<SourceCompressorThread *>(arg)->threadLoop();
}
bool
SourceCompressorThread::init()
{
JS_ASSERT(!thread);
lock = PR_NewLock();
if (!lock)
return false;
wakeup = PR_NewCondVar(lock);
if (!wakeup)
return false;
done = PR_NewCondVar(lock);
if (!done)
return false;
thread = PR_CreateThread(PR_USER_THREAD, compressorThread, this, PR_PRIORITY_NORMAL,
PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
if (!thread)
return false;
return true;
}
void
SourceCompressorThread::finish()
{
if (thread) {
PR_Lock(lock);
// We should only be compressing things when in the compiler.
JS_ASSERT(state == IDLE);
PR_NotifyCondVar(wakeup);
state = SHUTDOWN;
PR_Unlock(lock);
PR_JoinThread(thread);
}
if (wakeup)
PR_DestroyCondVar(wakeup);
if (done)
PR_DestroyCondVar(done);
if (lock)
PR_DestroyLock(lock);
}
void
SourceCompressorThread::threadLoop()
{
PR_Lock(lock);
while (true) {
switch (state) {
case SHUTDOWN:
PR_Unlock(lock);
return;
case IDLE:
PR_WaitCondVar(wakeup, PR_INTERVAL_NO_TIMEOUT);
break;
case COMPRESSING:
JS_ASSERT(tok);
JS_ASSERT(!tok->ss->ready());
tok->ss->considerCompressing(rt, tok->chars);
// We hold the lock, so no one should have changed this.
JS_ASSERT(state == COMPRESSING);
state = IDLE;
PR_NotifyCondVar(done);
break;
}
}
}
void
SourceCompressorThread::compress(SourceCompressionToken *sct)
{
if (tok)
// We have reentered the compiler. (This can happen through the
// debugger.) Complete the current compression before starting the next
// one.
waitOnCompression(tok);
JS_ASSERT(state == IDLE);
JS_ASSERT(!tok);
PR_Lock(lock);
tok = sct;
state = COMPRESSING;
PR_NotifyCondVar(wakeup);
PR_Unlock(lock);
}
void
SourceCompressorThread::waitOnCompression(SourceCompressionToken *userTok)
{
JS_ASSERT(userTok == tok);
JS_ASSERT(!tok->ss->onRuntime());
PR_Lock(lock);
if (state == COMPRESSING)
PR_WaitCondVar(done, PR_INTERVAL_NO_TIMEOUT);
JS_ASSERT(state == IDLE);
JS_ASSERT(tok->ss->ready());
tok->ss = NULL;
tok->chars = NULL;
tok = NULL;
PR_Unlock(lock);
}
#endif /* JS_THREADSAFE */
JSFixedString *
JSScript::sourceData(JSContext *cx)
{
return source->substring(cx, sourceStart, sourceEnd);
}
JSFixedString *
SourceDataCache::lookup(ScriptSource *ss)
{
if (!map_)
return NULL;
if (Map::Ptr p = map_->lookup(ss))
return p->value;
return NULL;
}
void
SourceDataCache::put(ScriptSource *ss, JSFixedString *str)
{
if (!map_) {
map_ = OffTheBooks::new_<Map>();
if (!map_)
return;
if (!map_->init()) {
purge();
return;
}
}
(void) map_->put(ss, str);
}
void
SourceDataCache::purge()
{
Foreground::delete_(map_);
map_ = NULL;
}
JSFixedString *
ScriptSource::substring(JSContext *cx, uint32_t start, uint32_t stop)
{
JS_ASSERT(ready());
const jschar *chars;
Rooted<JSFixedString *> cached(cx, NULL);
if (compressed()) {
cached = cx->runtime->sourceDataCache.lookup(this);
if (!cached) {
const size_t memlen = sizeof(jschar) * (length_ + 1);
jschar *decompressed = static_cast<jschar *>(cx->malloc_(memlen));
if (!decompressed)
return NULL;
if (!DecompressString(data.compressed, compressedLength,
reinterpret_cast<unsigned char *>(decompressed), memlen)) {
JS_ReportOutOfMemory(cx);
cx->free_(decompressed);
return NULL;
}
decompressed[length_] = 0;
cached = js_NewString(cx, decompressed, length_);
if (!cached) {
cx->free_(decompressed);
return NULL;
}
cx->runtime->sourceDataCache.put(this, cached);
}
chars = cached->getChars(cx);
JS_ASSERT(chars);
} else {
chars = data.source;
}
return js_NewStringCopyN(cx, chars + start, stop - start);
}
ScriptSource *
ScriptSource::createFromSource(JSContext *cx, const jschar *src, uint32_t length,
bool argumentsNotIncluded, SourceCompressionToken *tok)
{
ScriptSource *ss = static_cast<ScriptSource *>(cx->malloc_(sizeof(*ss)));
if (!ss)
return NULL;
const size_t memlen = length * sizeof(jschar);
ss->data.compressed = static_cast<unsigned char *>(cx->malloc_(memlen));
if (!ss->data.compressed) {
cx->free_(ss);
return NULL;
}
ss->next = NULL;
ss->length_ = length;
ss->marked = ss->onRuntime_ = false;
ss->argumentsNotIncluded_ = argumentsNotIncluded;
#ifdef DEBUG
ss->ready_ = false;
#endif
#ifdef JSGC_INCREMENTAL
/*
* During the IGC we need to ensure that source is marked whenever it is
* accessed even if the name was already in the table. At this point old
* scripts pointing to the source may no longer be reachable.
*/
if (cx->runtime->gcIncrementalState == MARK && cx->runtime->gcIsFull)
ss->marked = true;
#endif
#ifdef JS_THREADSAFE
if (tok) {
tok->ss = ss;
tok->chars = src;
cx->runtime->sourceCompressorThread.compress(tok);
} else
#endif
ss->considerCompressing(cx->runtime, src);
return ss;
}
void
ScriptSource::considerCompressing(JSRuntime *rt, const jschar *src)
{
JS_ASSERT(!ready());
const size_t memlen = length_ * sizeof(jschar);
const size_t COMPRESS_THRESHOLD = 512;
size_t compressedLen;
if (memlen >= COMPRESS_THRESHOLD &&
TryCompressString(reinterpret_cast<const unsigned char *>(src), memlen,
data.compressed, &compressedLen))
{
JS_ASSERT(compressedLen < memlen);
compressedLength = compressedLen;
void *mem = rt->realloc_(data.compressed, compressedLength);
data.compressed = static_cast<unsigned char *>(mem);
JS_ASSERT(data.compressed);
} else {
compressedLength = 0;
PodCopy(data.source, src, length_);
}
#ifdef DEBUG
ready_ = true;
#endif
}
void
SourceCompressionToken::ensureReady()
{
#ifdef JS_THREADSAFE
rt->sourceCompressorThread.waitOnCompression(this);
#endif
}
void
ScriptSource::attachToRuntime(JSRuntime *rt)
{
JS_ASSERT(!onRuntime());
next = rt->scriptSources;
rt->scriptSources = this;
onRuntime_ = true;
}
void
ScriptSource::destroy(JSRuntime *rt)
{
JS_ASSERT(ready());
JS_ASSERT(onRuntime());
rt->free_(data.compressed);
onRuntime_ = marked = false;
#ifdef DEBUG
ready_ = false;
#endif
rt->free_(this);
}
void
ScriptSource::sweep(JSRuntime *rt)
{
ScriptSource *next = rt->scriptSources, **prev = &rt->scriptSources;
while (next) {
ScriptSource *cur = next;
next = cur->next;
JS_ASSERT(cur->ready());
JS_ASSERT(cur->onRuntime());
if (cur->marked) {
cur->marked = false;
prev = &cur->next;
} else {
*prev = next;
cur->destroy(rt);
}
}
}
template<XDRMode mode>
bool
ScriptSource::performXDR(XDRState<mode> *xdr, ScriptSource **ssp)
{
class Cleanup {
JSContext *cx;
ScriptSource *ss;
public:
explicit Cleanup(JSContext *cx)
: cx(cx), ss(NULL) {}
~Cleanup()
{
if (ss) {
if (ss->data.compressed)
cx->free_(ss->data.compressed);
cx->free_(ss);
}
}
void protect(ScriptSource *source) { ss = source; }
void release() { ss = NULL; }
} cleanup(xdr->cx());
ScriptSource *ss = *ssp;
if (mode == XDR_DECODE) {
*ssp = static_cast<ScriptSource *>(xdr->cx()->malloc_(sizeof(ScriptSource)));
ss = *ssp;
if (!ss)
return false;
ss->marked = ss->onRuntime_ = ss->argumentsNotIncluded_ = false;
#ifdef DEBUG
ss->ready_ = false;
#endif
ss->data.compressed = NULL;
cleanup.protect(ss);
#ifdef JSGC_INCREMENTAL
// See comment in ScriptSource::createFromSource.
if (xdr->cx()->runtime->gcIncrementalState == MARK &&
xdr->cx()->runtime->gcIsFull)
ss->marked = true;
#endif
}
if (!xdr->codeUint32(&ss->length_))
return false;
if (!xdr->codeUint32(&ss->compressedLength))
return false;
uint8_t argumentsNotIncluded = ss->argumentsNotIncluded_;
if (!xdr->codeUint8(&argumentsNotIncluded))
return false;
ss->argumentsNotIncluded_ = argumentsNotIncluded;
size_t byteLen = ss->compressed() ? ss->compressedLength :
(ss->length_ * sizeof(jschar));
if (mode == XDR_DECODE) {
ss->data.compressed = static_cast<unsigned char *>(xdr->cx()->malloc_(byteLen));
if (!ss->data.compressed)
return false;
}
if (!xdr->codeBytes(ss->data.compressed, byteLen))
return false;
if (mode == XDR_DECODE) {
#ifdef DEBUG
ss->ready_ = true;
#endif
ss->attachToRuntime(xdr->cx()->runtime);
cleanup.release();
}
return true;
}
/*
* Shared script filename management.
*/
@ -1112,7 +1503,8 @@ ScriptDataSize(uint32_t length, uint32_t nsrcnotes, uint32_t natoms,
JSScript *
JSScript::Create(JSContext *cx, HandleObject enclosingScope, bool savedCallerFun,
JSPrincipals *principals, JSPrincipals *originPrincipals,
bool compileAndGo, bool noScriptRval, JSVersion version, unsigned staticLevel)
bool compileAndGo, bool noScriptRval, JSVersion version, unsigned staticLevel,
ScriptSource *ss, uint32_t bufStart, uint32_t bufEnd)
{
JSScript *script = js_NewGCScript(cx);
if (!script)
@ -1150,6 +1542,10 @@ JSScript::Create(JSContext *cx, HandleObject enclosingScope, bool savedCallerFun
}
script->staticLevel = uint16_t(staticLevel);
script->source = ss;
script->sourceStart = bufStart;
script->sourceEnd = bufEnd;
return script;
}
@ -1340,6 +1736,7 @@ JSScript::fullyInitFromEmitter(JSContext *cx, Handle<JSScript*> script, Bytecode
if (bce->constList.length() != 0)
bce->constList.finish(script->consts());
script->strictModeCode = bce->sc->inStrictMode();
script->explicitUseStrict = bce->sc->hasExplicitUseStrict();
script->bindingsAccessedDynamically = bce->sc->bindingsAccessedDynamically();
script->funHasExtensibleScope = bce->sc->funHasExtensibleScope();
script->hasSingletons = bce->hasSingletons;
@ -1779,7 +2176,8 @@ js::CloneScript(JSContext *cx, HandleObject enclosingScope, HandleFunction fun,
JSScript *dst = JSScript::Create(cx, enclosingScope, src->savedCallerFun,
cx->compartment->principals, src->originPrincipals,
src->compileAndGo, src->noScriptRval,
src->getVersion(), src->staticLevel);
src->getVersion(), src->staticLevel,
src->source, src->sourceStart, src->sourceEnd);
if (!dst) {
Foreground::free_(data);
return NULL;
@ -1815,6 +2213,7 @@ js::CloneScript(JSContext *cx, HandleObject enclosingScope, HandleFunction fun,
}
dst->cloneHasArray(src);
dst->strictModeCode = src->strictModeCode;
dst->explicitUseStrict = src->explicitUseStrict;
dst->bindingsAccessedDynamically = src->bindingsAccessedDynamically;
dst->funHasExtensibleScope = src->funHasExtensibleScope;
dst->hasSingletons = src->hasSingletons;
@ -2106,8 +2505,13 @@ JSScript::markChildren(JSTracer *trc)
if (enclosingScope_)
MarkObject(trc, &enclosingScope_, "enclosing");
if (IS_GC_MARKING_TRACER(trc) && filename)
MarkScriptFilename(trc->runtime, filename);
if (IS_GC_MARKING_TRACER(trc)) {
if (filename)
MarkScriptFilename(trc->runtime, filename);
if (trc->runtime->gcIsFull && source && source->onRuntime())
source->mark();
}
bindings.trace(trc);

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

@ -10,7 +10,6 @@
/*
* JS script descriptor.
*/
#include "jsatom.h"
#include "jsprvtd.h"
#include "jsdbgapi.h"
#include "jsclist.h"
@ -336,6 +335,8 @@ typedef HashMap<JSScript *,
DefaultHasher<JSScript *>,
SystemAllocPolicy> DebugScriptMap;
struct ScriptSource;
} /* namespace js */
struct JSScript : public js::gc::Cell
@ -436,6 +437,8 @@ struct JSScript : public js::gc::Cell
/* Persistent type information retained across GCs. */
js::types::TypeScript *types;
js::ScriptSource *source; /* source code */
private:
#ifdef JS_METHODJIT
JITScriptSet *jitInfo;
@ -455,6 +458,10 @@ struct JSScript : public js::gc::Cell
uint32_t natoms; /* length of atoms array */
uint32_t sourceStart;
uint32_t sourceEnd;
private:
uint32_t useCount; /* Number of times the script has been called
* or has had backedges taken. Reset if the
@ -468,6 +475,8 @@ struct JSScript : public js::gc::Cell
uint32_t idpad;
#endif
uint32_t PADDING;
// 16-bit fields.
private:
@ -511,6 +520,7 @@ struct JSScript : public js::gc::Cell
expression statement */
bool savedCallerFun:1; /* can call getCallerFunction() */
bool strictModeCode:1; /* code is in strict mode */
bool explicitUseStrict:1; /* code has "use strict"; explicitly */
bool compileAndGo:1; /* see Parser::compileAndGo */
bool bindingsAccessedDynamically:1; /* see ContextFlags' field of the same name */
bool funHasExtensibleScope:1; /* see ContextFlags' field of the same name */
@ -551,7 +561,8 @@ struct JSScript : public js::gc::Cell
static JSScript *Create(JSContext *cx, js::HandleObject enclosingScope, bool savedCallerFun,
JSPrincipals *principals, JSPrincipals *originPrincipals,
bool compileAndGo, bool noScriptRval,
JSVersion version, unsigned staticLevel);
JSVersion version, unsigned staticLevel,
js::ScriptSource *ss, uint32_t sourceStart, uint32_t sourceEnd);
// Three ways ways to initialize a JSScript. Callers of partiallyInit()
// and fullyInitTrivial() are responsible for notifying the debugger after
@ -607,6 +618,8 @@ struct JSScript : public js::gc::Cell
JSFunction *function() const { return function_; }
void setFunction(JSFunction *fun);
JSFixedString *sourceData(JSContext *cx);
/* Return whether this script was compiled for 'eval' */
bool isForEval() { return isCachedEval || isActiveEval; }
@ -937,6 +950,132 @@ js_CallNewScriptHook(JSContext *cx, JSScript *script, JSFunction *fun);
namespace js {
struct SourceCompressionToken;
struct ScriptSource
{
friend class SourceCompressorThread;
ScriptSource *next;
private:
union {
// When the script source is ready, compressedLength > 0 implies
// compressed holds the compressed data; otherwise, source holds the
// uncompressed source.
jschar *source;
unsigned char *compressed;
} data;
uint32_t length_;
uint32_t compressedLength;
bool marked:1;
bool onRuntime_:1;
bool argumentsNotIncluded_:1;
#ifdef DEBUG
bool ready_:1;
#endif
public:
static ScriptSource *createFromSource(JSContext *cx,
const jschar *src,
uint32_t length,
bool argumentsNotIncluded = false,
SourceCompressionToken *tok = NULL);
void attachToRuntime(JSRuntime *rt);
void mark() { JS_ASSERT(ready_); JS_ASSERT(onRuntime_); marked = true; }
void destroy(JSRuntime *rt);
uint32_t length() const { return length_; }
bool onRuntime() const { return onRuntime_; }
bool argumentsNotIncluded() const { return argumentsNotIncluded_; }
#ifdef DEBUG
bool ready() const { return ready_; }
#endif
JSFixedString *substring(JSContext *cx, uint32_t start, uint32_t stop);
// For the GC.
static void sweep(JSRuntime *rt);
// XDR handling
template <XDRMode mode>
static bool performXDR(XDRState<mode> *xdr, ScriptSource **ss);
private:
bool compressed() { return !!compressedLength; }
void considerCompressing(JSRuntime *rt, const jschar *src);
};
#ifdef JS_THREADSAFE
/*
* Background thread to compress JS source code. This happens only while parsing
* and bytecode generation is happening in the main thread. If needed, the
* compiler waits for compression to complete before returning.
*
* To use it, you have to have a SourceCompressionToken, tok, with tok.ss and
* tok.chars set to the proper values. When the SourceCompressionToken is
* destroyed, it makes sure the compression is complete. At this point tok.ss is
* ready to be attached to the runtime.
*/
class SourceCompressorThread
{
private:
enum {
// The compression thread is in the process of compression some source.
COMPRESSING,
// The compression thread is not doing anything and available to
// compress source.
IDLE,
// Set by finish() to tell the compression thread to exit.
SHUTDOWN
} state;
JSRuntime *rt;
SourceCompressionToken *tok;
PRThread *thread;
// Protects |state| and |tok| when it's non-NULL.
PRLock *lock;
// When it's idling, the compression thread blocks on this. The main thread
// uses it to notify the compression thread when it has source to be
// compressed.
PRCondVar *wakeup;
// The main thread can block on this to wait for compression to finish.
PRCondVar *done;
void threadLoop();
static void compressorThread(void *arg);
public:
explicit SourceCompressorThread(JSRuntime *rt)
: state(IDLE),
rt(rt),
tok(NULL),
thread(NULL),
lock(NULL),
wakeup(NULL),
done(NULL) {}
void finish();
bool init();
void compress(SourceCompressionToken *tok);
void waitOnCompression(SourceCompressionToken *userTok);
};
#endif
struct SourceCompressionToken
{
friend class ScriptSource;
friend class SourceCompressorThread;
private:
JSRuntime *rt;
ScriptSource *ss;
const jschar *chars;
public:
SourceCompressionToken(JSRuntime *rt)
: rt(rt), ss(NULL), chars(NULL) {}
~SourceCompressionToken()
{
JS_ASSERT_IF(!ss, !chars);
if (ss)
ensureReady();
}
void ensureReady();
};
extern void
CallDestroyScriptHook(FreeOp *fop, JSScript *script);

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

@ -23,8 +23,76 @@
#include "js/TemplateLib.h"
#include "js/Utility.h"
#include "zlib.h"
using namespace js;
static void *
zlib_alloc(void *cx, uInt items, uInt size)
{
return OffTheBooks::malloc_(items * size);
}
static void
zlib_free(void *cx, void *addr)
{
Foreground::free_(addr);
}
bool
js::TryCompressString(const unsigned char *inp, size_t inplen, unsigned char *out, size_t *outlen)
{
JS_ASSERT(inplen);
if (inplen >= UINT32_MAX)
return false;
z_stream zs;
zs.opaque = NULL;
zs.zalloc = zlib_alloc;
zs.zfree = zlib_free;
zs.next_in = (Bytef *)inp;
zs.avail_in = inplen;
zs.next_out = out;
zs.avail_out = inplen;
int ret = deflateInit(&zs, Z_DEFAULT_COMPRESSION);
if (ret != Z_OK) {
JS_ASSERT(ret == Z_MEM_ERROR);
return false;
}
ret = deflate(&zs, Z_FINISH);
DebugOnly<int> ret2 = deflateEnd(&zs);
JS_ASSERT(ret2 == Z_OK);
if (ret != Z_STREAM_END)
return false;
*outlen = inplen - zs.avail_out;
return true;
}
bool
js::DecompressString(const unsigned char *inp, size_t inplen, unsigned char *out, size_t outlen)
{
JS_ASSERT(inplen <= UINT32_MAX);
z_stream zs;
zs.zalloc = zlib_alloc;
zs.zfree = zlib_free;
zs.opaque = NULL;
zs.next_in = (Bytef *)inp;
zs.avail_in = inplen;
zs.next_out = out;
JS_ASSERT(outlen);
zs.avail_out = outlen;
int ret = inflateInit(&zs);
if (ret != Z_OK) {
JS_ASSERT(ret == Z_MEM_ERROR);
return false;
}
ret = inflate(&zs, Z_FINISH);
JS_ASSERT(ret == Z_STREAM_END);
ret = inflateEnd(&zs);
JS_ASSERT(ret == Z_OK);
return true;
}
#ifdef DEBUG
/* For JS_OOM_POSSIBLY_FAIL in jsutil.h. */
JS_PUBLIC_DATA(uint32_t) OOM_maxAllocations = UINT32_MAX;

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

@ -335,6 +335,21 @@ ClearAllBitArrayElements(size_t *array, size_t length)
array[i] = 0;
}
/*
* Attempt to compress some bytes. Return true if compression produced a
* string smaller than the input. The caller is responsible for allocating
* |out| to a string the same length as the input.
*/
bool TryCompressString(const unsigned char *inp, size_t inplen,
unsigned char *out, size_t *outlen);
/*
* Decompress a string. The caller must know the length of the output and
* allocate |out| to a string of that length.
*/
bool DecompressString(const unsigned char *inp, size_t inplen,
unsigned char *out, size_t outlen);
} /* namespace js */
#endif /* __cplusplus */

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

@ -3292,6 +3292,63 @@ Snarf(JSContext *cx, unsigned argc, jsval *vp)
return true;
}
static bool
DecompileFunctionSomehow(JSContext *cx, unsigned argc, Value *vp,
JSString *(*decompiler)(JSContext *, JSFunction *, unsigned))
{
CallArgs args = CallArgsFromVp(argc, vp);
if (args.length() < 1 || !args[0].isObject() || !args[0].toObject().isFunction()) {
args.rval().setUndefined();
return true;
}
JSString *result = decompiler(cx, args[0].toObject().toFunction(), 0);
if (!result)
return false;
args.rval().setString(result);
return true;
}
static JSBool
DecompileBody(JSContext *cx, unsigned argc, Value *vp)
{
return DecompileFunctionSomehow(cx, argc, vp, JS_DecompileFunctionBody);
}
static JSBool
DecompileFunction(JSContext *cx, unsigned argc, Value *vp)
{
return DecompileFunctionSomehow(cx, argc, vp, JS_DecompileFunction);
}
static JSBool
DecompileThisScript(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
JSScript *script = js_GetCurrentScript(cx);
JS_ASSERT(script);
JSString *result = JS_DecompileScript(cx, script, "test", 0);
if (!result)
return false;
args.rval().setString(result);
return true;
}
static JSBool
ThisFilename(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
JSScript *script = js_GetCurrentScript(cx);
if (!script || !script->filename) {
args.rval().setString(cx->runtime->emptyString);
return true;
}
JSString *filename = JS_NewStringCopyZ(cx, script->filename);
if (!filename)
return false;
args.rval().setString(filename);
return true;
}
static JSBool
Wrap(JSContext *cx, unsigned argc, jsval *vp)
{
@ -3688,6 +3745,22 @@ static JSFunctionSpecWithHelp shell_functions[] = {
"parent(obj)",
" Returns the parent of obj."),
JS_FN_HELP("decompileFunction", DecompileFunction, 1, 0,
"decompileFunction(func)",
" Decompile a function."),
JS_FN_HELP("decompileBody", DecompileBody, 1, 0,
"decompileBody(func)",
" Decompile a function's body."),
JS_FN_HELP("decompileThis", DecompileThisScript, 0, 0,
"decompileThis()",
" Decompile the currently executing script."),
JS_FN_HELP("thisFilename", ThisFilename, 0, 0,
"thisFilename()",
" Return the filename of the current script"),
JS_FN_HELP("wrap", Wrap, 1, 0,
"wrap(obj)",
" Wrap an object into a noop wrapper."),

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

@ -1,50 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var summary = "Function.prototype.toString should not quote XML literals";
var BUGNUMBER = 301692;
var actual = '';
var expect = '';
printBugNumber(BUGNUMBER);
START(summary);
actual = ConvertToString((function () { return <xml/>; }));
expect = 'function () { return <xml/>;}';
TEST(1, expect, actual);
actual = ConvertToString((function () { return <xml></xml>; }));
expect = 'function () { return <xml></xml>;}';
TEST(2, expect, actual);
actual = ConvertToString((function () { return <xml><morexml/></xml>; }));
expect = 'function () { return <xml><morexml/></xml>;}';
TEST(3, expect, actual);
actual = ConvertToString((function (k) { return <xml>{k}</xml>; }));
expect = 'function (k) { return <xml>{k}</xml>;}';
TEST(4, expect, actual);
actual = ConvertToString((function (k) { return <{k}/>; }));
expect = 'function (k) { return <{k}/>;}';
TEST(5, expect, actual);
actual = ConvertToString((function (k) { return <{k}>{k}</{k}>; }));
expect = 'function (k) { return <{k}>{k}</{k}>;}';
TEST(6, expect, actual);
actual = ConvertToString((function (k) { return <{k}
{k}={k} {"k"}={k + "world"}><{k + "k"}/></{k}>; }));
expect = 'function (k) ' +
'{ return <{k} {k}={k} {"k"}={k + "world"}><{k + "k"}/></{k}>;}';
TEST(7, expect, actual);
END();
function ConvertToString(f)
{
return f.toString().replace(/\n/g, '').replace(/[ ]+/g, ' ');
}

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

@ -1,58 +0,0 @@
/* -*- Mode: java; tab-width:8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var summary = "Operator .. should not implicitly quote its right operand";
var BUGNUMBER = 321547;
var actual = '';
var expect = '';
printBugNumber(BUGNUMBER);
START(summary);
function a(){
var x=<a><b><c>value c</c></b></a>;
return x..c;
}
actual = a.toString();
expect = 'function a() {\n' +
' var x = <a><b><c>value c</c></b></a>;\n' +
' return x..c;\n' +
'}';
actual = actual.replace(/[\n ]+/mg, ' ');
expect = expect.replace(/[\n ]+/mg, ' ');
TEST(1, expect, actual);
actual = String(a.valueOf());
expect = 'function a() {\n' +
' var x = <a><b><c>value c</c></b></a>;\n' +
' return x..c;\n' +
'}';
actual = actual.replace(/[\n ]+/mg, ' ');
expect = expect.replace(/[\n ]+/mg, ' ');
TEST(3, expect, actual);
actual = String(a);
expect = 'function a() {\n' +
' var x = <a><b><c>value c</c></b></a>;\n' +
' return x..c;\n' +
'}';
actual = actual.replace(/[\n ]+/mg, ' ');
expect = expect.replace(/[\n ]+/mg, ' ');
TEST(4, expect, actual);
actual = a();
expect = <c>value c</c>;
actual = actual.replace(/[\n ]+/mg, ' ');
expect = expect.replace(/[\n ]+/mg, ' ');
TEST(5, expect, actual);
END();

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

@ -1,21 +0,0 @@
/* -*- Mode: java; tab-width:8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var BUGNUMBER = 331558;
var summary = 'Decompiler: Missing = in default xml namespace statement';
var actual = '';
var expect = '';
printBugNumber(BUGNUMBER);
START(summary);
actual = (function () { default xml namespace = 'abc' }).toString();
expect = 'function () {\n default xml namespace = "abc";\n}';
TEST(1, expect, actual);
END();

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

@ -1,58 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//-----------------------------------------------------------------------------
var BUGNUMBER = "352097";
var summary = "Avoid adding unnecessary spaces to PIs";
var actual, expect;
printBugNumber(BUGNUMBER);
START(summary);
/**************
* BEGIN TEST *
**************/
var failed = false;
function assertContains(func, str)
{
if (func.toString().indexOf(str) < 0)
throw func.toString() + " does not contain " + str + "!";
}
try
{
var f = new Function("return <?f?>;");
assertContains(f, "<?f?>");
var g = new Function("return <?f ?>;");
assertContains(g, "<?f?>");
var h = new Function("return <?f ?>;");
assertContains(h, "<?f?>");
var i = new Function("return <?f i?>;");
assertContains(i, "<?f i?>");
var j = new Function("return <?f i ?>;");
assertContains(j, "<?f i ?>");
var k = new Function("return <?f i ?>;");
assertContains(k, "<?f i ?>");
var m = new Function("return <?f i ?>;");
assertContains(m, "<?f i ?>");
}
catch (ex)
{
failed = ex;
}
expect = false;
actual = failed;
TEST(1, expect, actual);

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

@ -1,27 +0,0 @@
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
* Contributors: Blake Kaplan, Bob Clary
*/
var summary = 'E4X - Function.prototype.toString should not quote {} ' +
'attribute values';
var BUGNUMBER = 302097;
var actual = '';
var expect = '';
printBugNumber(BUGNUMBER);
START(summary);
function f(k) {
return <xml k={k}/>;
}
actual = f.toString().replace(/</g, '&lt;');
expect = 'function f(k) {\n return &lt;xml k={k}/>;\n}';
TEST(1, expect, actual);
END();

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

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

@ -1,46 +0,0 @@
// |reftest| fails
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//-----------------------------------------------------------------------------
var BUGNUMBER = "352285";
var summary = "Decompiler escapes line breaks/backslashes in E4X literals";
var actual, expect;
printBugNumber(BUGNUMBER);
START(summary);
/**************
* BEGIN TEST *
**************/
var failed = false;
function assertCorrectDecompilation(xmlInitializer)
{
var func = new Function("return " + xmlInitializer);
var funcStr = func.toString();
if (funcStr.indexOf(xmlInitializer) < 0)
throw "'" + funcStr + "' does not contain '" + xmlInitializer + "'!";
}
try
{
assertCorrectDecompilation("<![CDATA[\\\\]]>");
assertCorrectDecompilation("<![CDATA[\n]]>");
assertCorrectDecompilation("<![CDATA[foo\nbar\nbaz]]>");
assertCorrectDecompilation("<!--f b\nc\n-->");
assertCorrectDecompilation("<?f b\n\nc\nc?>");
}
catch (ex)
{
failed = ex;
}
expect = false;
actual = failed;
TEST(1, expect, actual);

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

@ -1,29 +0,0 @@
/* -*- Mode: java; tab-width:8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var BUGNUMBER = 349814;
var summary = 'decompilation of e4x literals';
var actual = '';
var expect = '';
printBugNumber(BUGNUMBER);
START(summary);
var z = function ()
{
a =
<x>
<y/>
</x>;
};
expect = z + '';
actual = (eval("(" + z + ")")) + '';
compareSource(expect, actual, inSection(1) + summary);
END();

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

@ -1,23 +0,0 @@
/* -*- Mode: java; tab-width:8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var BUGNUMBER = 349815;
var summary = 'decompilation of parameterized e4x xmllist literal';
var actual = '';
var expect = '';
printBugNumber(BUGNUMBER);
START(summary);
var f = function (tag) { return <><{tag}></{tag}></>; }
expect = 'function (tag) {\n return <><{tag}></{tag}></>;\n}';
actual = f + '';
compareSource(expect, actual, inSection(1) + summary);
END();

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

@ -1,30 +0,0 @@
/* -*- Mode: java; tab-width:8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var BUGNUMBER = 349822;
var summary = 'decompilation of x.@[2]';
var actual = '';
var expect = '';
printBugNumber(BUGNUMBER);
START(summary);
expect = 'function () {\n return x.@[2];\n}';
try
{
var f = eval('(function () { return x.@[2]; })');
actual = f + '';
}
catch(ex)
{
actual = ex + '';
}
compareSource(expect, actual, inSection(1) + summary);
END();

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

@ -1,27 +0,0 @@
/* -*- Mode: java; tab-width:8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var BUGNUMBER = 349956;
var summary = 'decompilation of <x/>.@*';
var actual = '';
var expect = '';
printBugNumber(BUGNUMBER);
START(summary);
var f;
var g;
f = function () { <x/>.@* };
g = eval('(' + f + ')');
expect = f + '';
actual = g + '';
compareSource(expect, actual, inSection(1) + summary);
END();

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

@ -1,22 +0,0 @@
/* -*- Mode: java; tab-width:8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var BUGNUMBER = 350226;
var summary = 'decompilation of <x/>.@[*]';
var actual = '';
var expect = '';
printBugNumber(BUGNUMBER);
START(summary);
var f = function () { <x/>[@[*]]; }
expect = 'function () {\n <x/>[@[*]];\n}';
actual = f + '';
compareSource(expect, actual, inSection(1) + summary);
END();

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

@ -1,28 +0,0 @@
/* -*- Mode: java; tab-width:8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var BUGNUMBER = 350531;
var summary = "decompilation of function (){ return (@['a'])=='b'}";
var actual = '';
var expect = '';
printBugNumber(BUGNUMBER);
START(summary);
var f;
f = function (){ return (@['a'])=='b'}
expect = 'function () {\n return @["a"] == "b";\n}';
actual = f + '';
compareSource(expect, actual, inSection(1) + summary);
f = function (){ return (@['a']).toXMLString() }
expect = 'function () {\n return @["a"].toXMLString();\n}';
actual = f + '';
compareSource(expect, actual, inSection(2) + summary);
END();

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

@ -1,28 +0,0 @@
/* -*- Mode: java; tab-width:8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var BUGNUMBER = 351706;
var summary = 'decompilation of E4X literals with parens';
var actual = '';
var expect = '';
printBugNumber(BUGNUMBER);
START(summary);
var f;
f = function() { return <{m}/>.(y) }
expect = 'function() { return (<{m}/>).(y); }';
actual = f + '';
compareSource(expect, actual, inSection(1) + summary);
f = function() { return (<{m}/>).(y) }
expect = 'function() { return (<{m}/>).(y); }';
actual = f + '';
compareSource(expect, actual, inSection(2) + summary);
END();

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

@ -1,24 +0,0 @@
/* -*- Mode: java; tab-width:8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
* Contributor: Robert Sayre
*/
var summary = 'decompilation of XMLPI object initializer';
var BUGNUMBER = 351988;
var actual = '';
var expect = '';
printBugNumber(BUGNUMBER);
START(summary);
var f;
f = function() { var y = <?foo bar?>; }
actual = f + '';
expect = 'function () {\n var y = <?foo bar?>;\n}';
compareSource(expect, actual, inSection(1) + summary);
END();

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

@ -1,104 +0,0 @@
/* -*- Mode: java; tab-width:8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var BUGNUMBER = 352013;
var summary = 'Decompilation with new operator redeaux';
var actual = '';
var expect = '';
printBugNumber(BUGNUMBER);
START(summary);
var l, m, r;
var nTests = 0;
// ---------------------------------------------------------------
l = function () { (new x(y))[z]; };
expect = 'function () { (new x(y))[z]; }';
actual = l + '';
compareSource(expect, actual, inSection(++nTests) + summary);
m = function () { new (x(y))[z]; };
expect = 'function () { new (x(y)[z]); }';
actual = m + '';
compareSource(expect, actual, inSection(++nTests) + summary);
r = function () { new (x(y)[z]); };
expect = 'function () { new (x(y)[z]); }';
actual = r + '';
compareSource(expect, actual, inSection(++nTests) + summary);
// ---------------------------------------------------------------
l = function () { (new x(y)).@a; };
expect = 'function () { (new x(y)).@a; }';
actual = l + '';
compareSource(expect, actual, inSection(++nTests) + summary);
m = function () { new (x(y)).@a; };
expect = 'function () { new (x(y).@a); }';
actual = m + '';
compareSource(expect, actual, inSection(++nTests) + summary);
r = function () { new (x(y).@a); };
expect = 'function () { new (x(y).@a); }';
actual = r + '';
compareSource(expect, actual, inSection(++nTests) + summary);
// ---------------------------------------------------------------
l = function () { (new x(y)).@n::a; };
expect = 'function () { (new x(y)).@[n::a]; }';
actual = l + '';
compareSource(expect, actual, inSection(++nTests) + summary);
m = function () { new (x(y)).@n::a; };
expect = 'function () { new (x(y).@[n::a]); }';
actual = m + '';
compareSource(expect, actual, inSection(++nTests) + summary);
r = function () { new (x(y).@n::a); };
expect = 'function () { new (x(y).@[n::a]); }';
actual = r + '';
compareSource(expect, actual, inSection(++nTests) + summary);
// ---------------------------------------------------------------
l = function () { (new x(y)).n::z; };
expect = 'function () { (new x(y)).n::z; }';
actual = l + '';
compareSource(expect, actual, inSection(++nTests) + summary);
m = function () { new (x(y)).n::z; };
expect = 'function () { new (x(y).n::z); }';
actual = m + '';
compareSource(expect, actual, inSection(++nTests) + summary);
r = function () { new (x(y).n::z); };
expect = 'function () { new (x(y).n::z); }';
actual = r + '';
compareSource(expect, actual, inSection(++nTests) + summary);
// ---------------------------------------------------------------
l = function () { (new x(y)).n::[z]; };
expect = 'function () { (new x(y)).n::[z]; }';
actual = l + '';
compareSource(expect, actual, inSection(++nTests) + summary);
m = function () { new (x(y)).n::[z]; };
expect = 'function () { new (x(y).n::[z]); }';
actual = m + '';
compareSource(expect, actual, inSection(++nTests) + summary);
r = function () { new (x(y).n::[z]); };
expect = 'function () { new (x(y).n::[z]); }';
actual = r + '';
compareSource(expect, actual, inSection(++nTests) + summary);
END();

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

@ -1,21 +0,0 @@
/* -*- Mode: java; tab-width:8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var BUGNUMBER = 352459;
var summary = 'decompilation for 4..@x++';
var actual = '';
var expect = '';
printBugNumber(BUGNUMBER);
START(summary);
var f = (function() { return 4..@x++; } );
expect = 'function() { return (4).@x++; }';
actual = f + '';
compareSource(expect, actual, inSection(1) + summary);
END();

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

@ -1,21 +0,0 @@
/* -*- Mode: java; tab-width:8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var BUGNUMBER = 352649;
var summary = 'decompilation of e4x literal after |if| block';
var actual = '';
var expect = '';
printBugNumber(BUGNUMBER);
START(summary);
var f = function() { if(g) p; (<x/>.i) }
expect = 'function() { if(g) {p;} <x/>.i; }';
actual = f + '';
compareSource(expect, actual, inSection(1) + summary);
END();

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

@ -1,33 +0,0 @@
/* -*- Mode: java; tab-width:8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var BUGNUMBER = 352789;
var summary = 'Decompilation of new and .@';
var actual = '';
var expect = '';
printBugNumber(BUGNUMBER);
START(summary);
var f;
f = function() { return new (a()).@z; };
expect = 'function() { return new (a().@z); }';
actual = f + '';
compareSource(expect, actual, inSection(1) + summary);
f = function () { return new a().@z; };
expect = 'function () { return (new a).@z; }';
actual = f + '';
compareSource(expect, actual, inSection(2) + summary);
f = function () { return (new a).@z; };
expect = 'function () { return (new a).@z; }';
actual = f + '';
compareSource(expect, actual, inSection(3) + summary);
END();

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

@ -1,21 +0,0 @@
/* -*- Mode: java; tab-width:8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var BUGNUMBER = 355101;
var summary = 'XML Filtering predicate operator';
var actual = '';
var expect = '';
printBugNumber(BUGNUMBER);
START(summary);
var f = function () { return i.(true); }
expect = 'function () { return i.(true); }';
actual = f + '';
compareSource(expect, actual, inSection(1) + summary);
END();

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

@ -1,28 +0,0 @@
/* -*- Mode: java; tab-width:8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var BUGNUMBER = 355474;
var summary = 'Iterating over XML with WAY_TOO_MUCH_GC';
var actual = '';
var expect = '';
printBugNumber(BUGNUMBER);
START(summary);
var f = function () { for each (var z in <y/>) { print(z); } };
expect = 'function () { for each (var z in <y/>) { print(z); } }';
actual = f + '';
compareSource(expect, actual, inSection(1) + summary);
expect = actual = 'No Hang';
f();
f();
TEST(2, expect, actual);
END();

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

@ -1,23 +0,0 @@
// |reftest| skip -- obsolete test
/* -*- Mode: java; tab-width:8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var BUGNUMBER = 373678;
var summary = 'Missing quotes around string in decompilation, ' +
'with for..in and do..while';
var actual = '';
var expect = '';
printBugNumber(BUGNUMBER);
START(summary);
var f = function() { do {for(a.b in []) { } } while("c\\d"); };
expect = 'function() { do {for(a.b in []) { } } while("c\\\\d"); }';
actual = f + '';
compareSource(expect, actual, inSection(1) + summary);
END();

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

@ -1,33 +0,0 @@
// |reftest| require-or(debugMode,skip)
/* -*- Mode: java; tab-width:8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var summary = 'trap should not change decompilation <x/>';
var BUGNUMBER = 429249
var actual = '';
var expect = '';
printBugNumber(BUGNUMBER);
START(summary);
function g() {
return <x/>;
}
expect = 'function g() { return <x/>; }';
actual = g + '';
compareSource(expect, actual, summary + ' : before trap');
if (typeof trap == 'function' && typeof setDebug == 'function')
{
setDebug(true);
trap(g, 0, "");
actual = g + '';
compareSource(expect, actual, summary + ' : after trap');
}
END();

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

@ -1,23 +0,0 @@
/* -*- Mode: java; tab-width:8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var summary = 'Decompilation of ({0: (4, <></>)})';
var BUGNUMBER = 461233;
var actual = '';
var expect = '';
printBugNumber(BUGNUMBER);
START(summary);
var f = (function() { return ({0: (4, <></>) }); });
expect = 'function() { return {0: (4, <></>) }; }';
actual = f + '';
compareSource(expect, actual, expect)
END();

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

@ -1,23 +0,0 @@
/* -*- Mode: java; tab-width:8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
* Contributor:
* Rasmus Jensen <rje(a)dbc.dk>
*/
var summary = 'Uneval+eval of XML containing string with {';
var BUGNUMBER = 463360;
var actual = '';
var expect = '';
printBugNumber(BUGNUMBER);
START(summary);
actual = eval(uneval(XML("<a>{</a>")));
expect = XML("<a>{</a>");
compareSource(expect, actual, inSection(1) + summary);
END();

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

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

@ -1,28 +0,0 @@
/* -*- Mode: java; tab-width:8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var summary = "Operator .. should not implicitly quote its right operand";
var BUGNUMBER = 321547;
var actual = '';
var expect = '';
printBugNumber(BUGNUMBER);
START(summary);
function a(){
var x=<a><b><c>value c</c></b></a>;
return x..c;
}
actual = a.toSource();
expect = 'function a() {var x = <a><b><c>value c</c></b></a>;return x..c;}';
actual = actual.replace(/[\n ]+/mg, ' ');
expect = expect.replace(/[\n ]+/mg, ' ');
TEST(2, expect, actual);
END();

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

@ -23,19 +23,16 @@ function test()
var code;
code = '(function() { label1: for (;;) { continue \n label1; }})';
expect = '(function() { label1: for (;;) { continue ; label1; }})';
actual = uneval(eval(code));
compareSource(expect, actual, summary + ': ' + code);
compareSource(code, actual, summary + ': ' + code);
code = '(function() { label2: for (;;) { break \n label2; }})';
expect = '(function() { label2: for (;;) { break ; label2; }})';
actual = uneval(eval(code));
compareSource(expect, actual, summary + ': ' + code);
compareSource(code, actual, summary + ': ' + code);
code = '(function() { return \n x++; })';
expect = '(function() { return ; x++; })';
actual = uneval(eval(code));
compareSource(expect, actual, summary + ': ' + code);
compareSource(code, actual, summary + ': ' + code);
print('see bug 256617');
code = '(function() { throw \n x++; })';

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

@ -1,17 +0,0 @@
var a = function (t) {
return t % 0;
}
var b = function (t) {
return t % "";
}
var c = function (t) {
return t % ("" + "");
}
assertEq(a.toString(), b.toString());
assertEq(a.toString(), c.toString());
if (typeof reportCompare === "function")
reportCompare(true, true);

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

@ -22,54 +22,6 @@ function f2novar(o){with(this)for(x in o)printStatus(o[x]); return x}
function f3(i,o){for(var x=i in o)printStatus(o[x]); return x}
function f4(i,o){with(this)for(var x=i in o)printStatus(o[x]); return x}
const f1src =
"function f1(o) {\n" +
" for (var x in o) {\n" +
" printStatus(o[x]);\n" +
" }\n" +
" return x;\n" +
"}";
const f2src =
"function f2(o) {\n" +
" with (this) {\n" +
" for (var x in o) {\n" +
" printStatus(o[x]);\n" +
" }\n" +
" }\n" +
" return x;\n" +
"}";
const f2novarsrc =
"function f2novar(o) {\n" +
" with (this) {\n" +
" for (x in o) {\n" +
" printStatus(o[x]);\n" +
" }\n" +
" }\n" +
" return x;\n" +
"}";
const f3src =
"function f3(i, o) {\n" +
" var x = i;\n" +
" for (x in o) {\n" +
" printStatus(o[x]);\n" +
" }\n" +
" return x;\n" +
"}";
const f4src =
"function f4(i, o) {\n" +
" with (this) {\n" +
" var x = i;\n" +
" for (x in o) {\n" +
" printStatus(o[x]);\n" +
" }\n" +
" }\n" +
" return x;\n" +
"}";
var t=0;
function assert(c)
{
@ -86,21 +38,6 @@ function assert(c)
reportCompare(expect, actual, summary);
}
if (dodis && this.dis) dis(f1);
assert(f1 == f1src);
if (dodis && this.dis) dis(f2);
assert(f2 == f2src);
if (dodis && this.dis) dis(f2novar);
assert(f2novar == f2novarsrc);
if (dodis && this.dis) dis(f3);
assert(f3 == f3src);
if (dodis && this.dis) dis(f4);
assert(f4 == f4src);
assert(f1([]) == undefined);
assert(f1(['first']) == 0);

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

@ -1,63 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//-----------------------------------------------------------------------------
var BUGNUMBER = 349648;
var summary = 'Extra "[" in decomilation of nested array comprehensions';
var actual = '';
var expect = '';
//-----------------------------------------------------------------------------
test();
//-----------------------------------------------------------------------------
function test()
{
enterFunc ('test');
printBugNumber(BUGNUMBER);
printStatus (summary);
var f;
f = function(){ [[0 for (x in [])] for (y in []) ]; };
expect = 'function () {\n [[0 for (x in [])] for (y in [])];\n}';
actual = f + '';
reportCompare(expect, actual, summary + ':1');
f = function(){ [[0 for (x in [])] for (y in []) ]; };
expect = 'function () {\n [[0 for (x in [])] for (y in [])];\n}';
actual = f + '';
reportCompare(expect, actual, summary + ':2');
f = function(){ [[0 for (x in [])] for (yyyyyyyyyyy in []) ]; }
expect = 'function () {\n [[0 for (x in [])] for (yyyyyyyyyyy in [])];\n}';
actual = f + '';
reportCompare(expect, actual, summary + ':3');
f = function(){ [0 for (x in [])]; }
expect = 'function () {\n [0 for (x in [])];\n}';
actual = f + '';
reportCompare(expect, actual, summary + ':4');
f = function(){ [[[0 for (x in [])] for (yyyyyyyyyyy in []) ]
for (zzz in [])]; }
expect = 'function () {\n [[[0 for (x in [])] for (yyyyyyyyyyy in [])]' +
' for (zzz in [])];\n}';
actual = f + '';
reportCompare(expect, actual, summary + ':5');
f = function(){ [[0 for (x in [])] for (y in []) ]; }
expect = 'function () {\n [[0 for (x in [])] for (y in [])];\n}';
actual = f + '';
reportCompare(expect, actual, summary + ':6');
f = function(){ [[11 for (x in [])] for (y in []) ]; }
expect = 'function () {\n [[11 for (x in [])] for (y in [])];\n}';
actual = f + '';
reportCompare(expect, actual, summary + ':7');
exitFunc ('test');
}

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

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

@ -1,29 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//-----------------------------------------------------------------------------
var BUGNUMBER = 344120;
var summary = 'function to source with numeric labels';
var actual = '';
var expect;
//-----------------------------------------------------------------------------
test();
//-----------------------------------------------------------------------------
function test()
{
enterFunc ('test');
printBugNumber(BUGNUMBER);
printStatus (summary);
expect = 'function () { x = {1:1};}';
actual = ''+function (){x={1:1}}
compareSource(expect, actual, summary);
exitFunc ('test');
}

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

@ -1,29 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//-----------------------------------------------------------------------------
var BUGNUMBER = 346892;
var summary = 'decompilation of new Function("3")';
var actual = '';
var expect = '';
//-----------------------------------------------------------------------------
test();
//-----------------------------------------------------------------------------
function test()
{
enterFunc ('test');
printBugNumber(BUGNUMBER);
printStatus (summary);
expect = 'function anonymous() {\n}';
actual = (new Function("3")) + '';
compareSource(expect, actual, summary);
exitFunc ('test');
}

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

@ -1,58 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//-----------------------------------------------------------------------------
var BUGNUMBER = 346902;
var summary = 'uneval expressions with object literals';
var actual = '';
var expect = '';
//-----------------------------------------------------------------------------
test();
//-----------------------------------------------------------------------------
function test()
{
enterFunc ('test');
printBugNumber(BUGNUMBER);
printStatus (summary);
var f;
expect =
'function () {\n' +
' ({}[alert(5)]);\n' +
'}';
try
{
f = eval('(function () { 1 ? {}[alert(5)] : 0; })');
actual = f + '';
compareSource(expect, actual, summary);
}
catch(ex)
{
actual = ex + '';
reportCompare(expect, actual, summary);
}
expect =
'function () {\n' +
' [alert(5)];\n' +
'}';
try
{
f = eval('(function () { {}[alert(5)]; })');
actual = f + '';
compareSource(expect, actual, summary);
}
catch(ex)
{
actual = ex + '';
reportCompare(expect, actual, summary);
}
exitFunc ('test');
}

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

@ -1,123 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//-----------------------------------------------------------------------------
var BUGNUMBER = 346904;
var summary = 'uneval expressions with double negation, negation decrement';
var actual = '';
var expect = '';
//-----------------------------------------------------------------------------
test();
//-----------------------------------------------------------------------------
function test()
{
enterFunc ('test');
printBugNumber(BUGNUMBER);
printStatus (summary);
var f;
// - --
expect =
'function () {\n' +
' return - --x;\n' +
'}';
try
{
f = eval('(function () { return - --x; })');
actual = f + '';
compareSource(expect, actual, summary);
}
catch(ex)
{
actual = ex + '';
reportCompare(expect, actual, summary);
}
// - -
expect =
'function () {\n' +
' return - - x;\n' +
'}';
try
{
f = eval('(function () { return - - x; })');
actual = f + '';
compareSource(expect, actual, summary);
}
catch(ex)
{
actual = ex + '';
reportCompare(expect, actual, summary);
}
// ---
expect = 'SyntaxError';
try
{
f = eval('(function () { return ---x; })');
actual = f + '';
compareSource(expect, actual, summary);
}
catch(ex)
{
actual = ex.name;
reportCompare(expect, actual, summary);
}
// + ++
expect =
'function () {\n' +
' return + ++x;\n' +
'}';
try
{
f = eval('(function () { return + ++x; })');
actual = f + '';
compareSource(expect, actual, summary);
}
catch(ex)
{
actual = ex + '';
reportCompare(expect, actual, summary);
}
// + +
expect =
'function () {\n' +
' return + + x;\n' +
'}';
try
{
f = eval('(function () { return + + x; })');
actual = f + '';
compareSource(expect, actual, summary);
}
catch(ex)
{
actual = ex + '';
reportCompare(expect, actual, summary);
}
// +++
expect = 'SyntaxError';
try
{
f = eval('(function () { return +++x; })');
actual = f + '';
}
catch(ex)
{
actual = ex.name;
}
reportCompare(expect, actual, summary);
exitFunc ('test');
}

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

@ -1,31 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//-----------------------------------------------------------------------------
var BUGNUMBER = 346915;
var summary = 'Optimize decompilation of delete expressions';
var actual = '';
var expect = '';
//-----------------------------------------------------------------------------
test();
//-----------------------------------------------------------------------------
function test()
{
enterFunc ('test');
printBugNumber(BUGNUMBER);
printStatus (summary);
var f;
f = function() { delete 3; };
expect = 'function () {\n}';
actual = f + '';
compareSource(expect, actual, summary);
exitFunc ('test');
}

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

@ -1,37 +0,0 @@
// |reftest| skip -- obsolete test
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//-----------------------------------------------------------------------------
var BUGNUMBER = 349484;
var summary = 'Incorrect decompilation of import/export statements';
var actual = 'No Crash';
var expect = 'No Crash';
//-----------------------------------------------------------------------------
test();
//-----------------------------------------------------------------------------
function test()
{
enterFunc ('test');
printBugNumber(BUGNUMBER);
printStatus (summary);
expect = 'function () {\n export x;\n alert(5);\n}';
var f = function() { export x; alert(5); };
actual = f.toString();
print(f.toString());
compareSource(expect, actual, summary);
expect = 'function () {\n import o.x;\n alert(5);\n}';
f = function () { import o.x; alert(5); }
actual = f.toString();
print(f.toString());
compareSource(expect, actual, summary);
exitFunc ('test');
}

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

@ -1,36 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//-----------------------------------------------------------------------------
var BUGNUMBER = 349489;
var summary = 'Incorrect decompilation of labeled useless statements';
var actual = 'No Crash';
var expect = 'No Crash';
//-----------------------------------------------------------------------------
test();
//-----------------------------------------------------------------------------
function test()
{
enterFunc ('test');
printBugNumber(BUGNUMBER);
printStatus (summary);
expect = 'function () {\nL:\n 3;\n}';
var f = function() { L: 3; };
actual = f.toString();
print(f.toString());
compareSource(expect, actual, summary);
expect = 'function () {\nL:\n 3;\n alert(5);\n}';
f = function() { L: 3; alert(5); }
actual = f.toString();
print(f.toString());
compareSource(expect, actual, summary);
exitFunc ('test');
}

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

@ -1,46 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//-----------------------------------------------------------------------------
var BUGNUMBER = 349491;
var summary = 'Incorrect decompilation due to assign to const';
var actual = 'No Crash';
var expect = 'No Crash';
//-----------------------------------------------------------------------------
test();
//-----------------------------------------------------------------------------
function test()
{
enterFunc ('test');
printBugNumber(BUGNUMBER);
printStatus (summary);
var a;
a = function () { const z = 3; g = 7; g = z += 1; return g };
expect = a();
actual = (eval('(' + a + ')'))();
reportCompare(expect, actual, summary);
a = function () { const z = 3; return z += 2 };
expect = a();
actual = (eval('(' + a + ')'))();
reportCompare(expect, actual, summary);
expect = 'function () {\n const z = 3;\n}';
a = function () { const z = 3; z = 4; }
actual = a.toString();
compareSource(expect, actual, summary);
expect = 'function () {\n const z = 3;\n}';
a = function () { const z = 3; 4; }
actual = a.toString();
compareSource(expect, actual, summary);
exitFunc ('test');
}

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

@ -1,30 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//-----------------------------------------------------------------------------
var BUGNUMBER = 349596;
var summary = 'decompilation of labeled if(0)...';
var actual = '';
var expect = '';
//-----------------------------------------------------------------------------
test();
//-----------------------------------------------------------------------------
function test()
{
enterFunc ('test');
printBugNumber(BUGNUMBER);
printStatus (summary);
var f = function() { L: if (0) return 5 }
expect = 'function () {\n L: {\n }\n}';
actual = f + '';
compareSource(expect, actual, summary);
exitFunc ('test');
}

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

@ -1,32 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//-----------------------------------------------------------------------------
var BUGNUMBER = 349650;
var summary = 'Number getting parens replaces last character of identifier in decompilation of array comprehension';
var actual = '';
var expect = '';
//-----------------------------------------------------------------------------
test();
//-----------------------------------------------------------------------------
function test()
{
enterFunc ('test');
printBugNumber(BUGNUMBER);
printStatus (summary);
var f;
f = function() { [5[7] for (y in window)]; }
expect = 'function () {\n [(5)[7] for (y in window)];\n}';
actual = f + '';
compareSource(expect, actual, summary);
exitFunc ('test');
}

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

@ -1,35 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//-----------------------------------------------------------------------------
var BUGNUMBER = 349663;
var summary = 'decompilation of Function with const *=';
var actual = '';
var expect = '';
//-----------------------------------------------------------------------------
test();
//-----------------------------------------------------------------------------
function test()
{
enterFunc ('test');
printBugNumber(BUGNUMBER);
printStatus (summary);
var f, g;
f = function() { const h; for(null; h *= ""; null) ; }
g = eval('(' + f + ')');
expect = f + '';
actual = g + '';
print(f);
compareSource(expect, actual, summary);
exitFunc ('test');
}

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

@ -1,36 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//-----------------------------------------------------------------------------
var BUGNUMBER = 350242;
var summary = 'decompilation of delete 0x11.x';
var actual = '';
var expect = '';
//-----------------------------------------------------------------------------
test();
//-----------------------------------------------------------------------------
function test()
{
enterFunc ('test');
printBugNumber(BUGNUMBER);
printStatus (summary);
var f;
f = function () { delete 0x11.x }
expect = 'function () {\n delete (17).x;\n}';
actual = f + '';
compareSource(expect, actual, summary);
f = function () { delete (17).x }
expect = 'function () {\n delete (17).x;\n}';
actual = f + '';
compareSource(expect, actual, summary);
exitFunc ('test');
}

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

@ -1,31 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//-----------------------------------------------------------------------------
var BUGNUMBER = 350263;
var summary = 'decompilation of labeled if(1);';
var actual = '';
var expect = '';
//-----------------------------------------------------------------------------
test();
//-----------------------------------------------------------------------------
function test()
{
enterFunc ('test');
printBugNumber(BUGNUMBER);
printStatus (summary);
var f;
f = function () { L: if(1); }
expect = 'function () {\n L: {\n }\n}';
actual = f + '';
compareSource(expect, actual, summary);
exitFunc ('test');
}

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

@ -1,31 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//-----------------------------------------------------------------------------
var BUGNUMBER = 350271;
var summary = 'decompilation if (0x10.(a))';
var actual = '';
var expect = '';
//-----------------------------------------------------------------------------
test();
//-----------------------------------------------------------------------------
function test()
{
enterFunc ('test');
printBugNumber(BUGNUMBER);
printStatus (summary);
var f;
f = function () { if(0x10.(a)) { h(); } }
expect = 'function () {\n if ((16).(a)) {\n h();\n }\n}';
actual = f + '';
compareSource(expect, actual, summary);
exitFunc ('test');
}

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

@ -1,60 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//-----------------------------------------------------------------------------
var BUGNUMBER = 350666;
var summary = 'decompilation for (;; delete expr)';
var actual = '';
var expect = '';
//-----------------------------------------------------------------------------
test();
//-----------------------------------------------------------------------------
function test()
{
enterFunc ('test');
printBugNumber(BUGNUMBER);
printStatus (summary);
var f;
f = function () { for(;; delete y.(x)) { } }
actual = f + '';
expect = 'function () {\n for (;; y.(x), true) {\n }\n}';
compareSource(expect, actual, summary);
try
{
eval('(' + expect + ')');
actual = 'No Error';
}
catch(ex)
{
actual = ex + '';
}
expect = 'No Error';
reportCompare(expect, actual, summary);
f = function () { for(;; delete (y+x)) { } }
actual = f + '';
expect = 'function () {\n for (;; y + x, true) {\n }\n}';
compareSource(expect, actual, summary);
try
{
eval('(' + expect + ')');
actual = 'No Error';
}
catch(ex)
{
actual = ex + '';
}
expect = 'No Error';
reportCompare(expect, actual, summary);
exitFunc ('test');
}

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

@ -1,36 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//-----------------------------------------------------------------------------
var BUGNUMBER = 350670;
var summary = 'decompilation of (for(z() in x)';
var actual = '';
var expect = '';
//-----------------------------------------------------------------------------
test();
//-----------------------------------------------------------------------------
function test()
{
enterFunc ('test');
printBugNumber(BUGNUMBER);
printStatus (summary);
var f;
f = function() { for(z() in x) { } }
expect = 'function () {\n for (z() in x) {\n }\n}';
actual = f + '';
compareSource(expect, actual, summary);
f = function() { for(z(12345678) in x) { } }
expect = 'function () {\n for (z(12345678) in x) {\n }\n}';
actual = f + '';
compareSource(expect, actual, summary);
exitFunc ('test');
}

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

@ -1,32 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//-----------------------------------------------------------------------------
var BUGNUMBER = 351104;
var summary = 'decompilation of for with ternary as initializer';
var actual = '';
var expect = '';
//-----------------------------------------------------------------------------
test();
//-----------------------------------------------------------------------------
function test()
{
enterFunc ('test');
printBugNumber(BUGNUMBER);
printStatus (summary);
var f;
f = function () { for((0 ? 2 : ({})); ; ) { } }
expect = 'function () {\n for ({};;) {\n }\n}';
actual = f + '';
compareSource(expect, actual, summary);
exitFunc ('test');
}

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

@ -1,34 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//-----------------------------------------------------------------------------
var BUGNUMBER = 351219;
var summary = 'Decompilation of immutable infinity, NaN';
var actual = '';
var expect = '';
//-----------------------------------------------------------------------------
test();
//-----------------------------------------------------------------------------
function test()
{
enterFunc ('test');
printBugNumber(BUGNUMBER);
printStatus (summary);
var f = function () { return 2e308 };
expect = 'function () { return 1 / 0; }';
actual = f + '';
compareSource(expect, actual, summary + ' decompile Infinity as 1/0');
f = function () { var NaN = 1 % 0; return NaN };
expect = 'function () { var NaN = 0 / 0; return NaN; }';
actual = f + '';
compareSource(expect, actual, summary + ': decompile NaN as 0/0');
exitFunc ('test');
}

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

@ -1,31 +0,0 @@
// |reftest| skip -- obsolete test
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//-----------------------------------------------------------------------------
var BUGNUMBER = 351336;
var summary = 'decompilation of for initialization containing for';
var actual = '';
var expect = '';
//-----------------------------------------------------------------------------
test();
//-----------------------------------------------------------------------------
function test()
{
enterFunc ('test');
printBugNumber(BUGNUMBER);
printStatus (summary);
var f = function () { for (("p" in a); 0;) { } }
expect = 'function () {\n for (("p" in a); 0;) {\n }\n}';
actual = f + '';
compareSource(expect, actual, summary);
exitFunc ('test');
}

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

@ -1,31 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//-----------------------------------------------------------------------------
var BUGNUMBER = 351597;
var summary = 'decompilation of new expression with extra parens';
var actual = '';
var expect = '';
//-----------------------------------------------------------------------------
test();
//-----------------------------------------------------------------------------
function test()
{
enterFunc ('test');
printBugNumber(BUGNUMBER);
printStatus (summary);
var f;
f = function() { new ((x=a))(y) }
expect = 'function () {\n new (x = a)(y);\n}';
actual = f + '';
compareSource(expect, actual, summary);
exitFunc ('test');
}

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

@ -1,31 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//-----------------------------------------------------------------------------
var BUGNUMBER = 351625;
var summary = 'decompilation of object literal';
var actual = '';
var expect = '';
//-----------------------------------------------------------------------------
test();
//-----------------------------------------------------------------------------
function test()
{
enterFunc ('test');
printBugNumber(BUGNUMBER);
printStatus (summary);
var f;
f = function() { ({a:b, c:3}); }
expect = 'function () {\n ({a:b, c:3});\n}';
actual = f + '';
compareSource(expect, actual, summary);
exitFunc ('test');
}

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

@ -1,32 +0,0 @@
// |reftest| skip -- obsolete test
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//-----------------------------------------------------------------------------
var BUGNUMBER = 351626;
var summary = 'decompilation of if(lamda)';
var actual = '';
var expect = '';
//-----------------------------------------------------------------------------
test();
//-----------------------------------------------------------------------------
function test()
{
enterFunc ('test');
printBugNumber(BUGNUMBER);
printStatus (summary);
var f;
f = function () { if (function () {}) { g(); } }
actual = f + '';
expect = 'function () {\n if (function () {}) {\n g();\n }\n}';
compareSource(expect, actual, summary);
exitFunc ('test');
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше