1
0
forked from mirrors/0ad

# Compile gameplay scripts in strict mode.

Fixes #487.

This was SVN commit r7456.
This commit is contained in:
Ykkrosh
2010-04-14 18:57:50 +00:00
parent 3117f52d7c
commit 3a1abb5d8f
2 changed files with 81 additions and 17 deletions
+22 -17
View File
@@ -62,6 +62,12 @@ JSClass global_class = {
void ErrorReporter(JSContext* UNUSED(cx), const char* message, JSErrorReport* report)
{
// XXX Ugly hack: we want to compile code with 'use strict' and with JSOPTION_STRICT,
// but the latter causes the former to be reported as a useless expression, so
// ignore that specific warning here
if (report->flags == 5 && report->lineno == 0 && report->errorNumber == 163)
return;
std::stringstream msg;
bool isWarning = JSREPORT_IS_WARNING(report->flags);
msg << (isWarning ? "JavaScript warning: " : "JavaScript error: ");
@@ -152,19 +158,6 @@ ScriptInterface_impl::~ScriptInterface_impl()
}
}
static JSBool LoadScript(JSContext* cx, const jschar* chars, uintN length, const char* filename, jsval* rval)
{
JSFunction* func = JS_CompileUCFunction(cx, NULL, NULL, 0, NULL, chars, length, filename, 1);
if (!func)
return JS_FALSE;
JS_AddRoot(cx, &func); // TODO: do we need to root this?
*rval = OBJECT_TO_JSVAL((JSObject*)func);
jsval scriptRval;
JSBool ok = JS_CallFunction(cx, NULL, func, 0, NULL, &scriptRval);
JS_RemoveRoot(cx, &func);
return ok;
}
void ScriptInterface_impl::Register(const char* name, JSNative fptr, uintN nargs)
{
JS_DefineFunction(m_cx, m_nativeScope, name, fptr, nargs, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
@@ -434,10 +427,22 @@ bool ScriptInterface::SetPrototype(jsval obj, jsval proto)
bool ScriptInterface::LoadScript(const std::wstring& filename, const std::wstring& code)
{
std::string fnAscii(filename.begin(), filename.end());
utf16string codeUtf16(code.begin(), code.end());
jsval rval;
JSBool ok = ::LoadScript(m->m_cx, reinterpret_cast<const jschar*> (codeUtf16.c_str()), (uintN)(codeUtf16.length()),
fnAscii.c_str(), &rval);
// Compile the code in strict mode, to encourage better coding practices and
// to possibly help SpiderMonkey with optimisations
std::wstring codeStrict = L"\"use strict\";\n" + code;
utf16string codeUtf16(codeStrict.begin(), codeStrict.end());
uintN lineNo = 0; // put the automatic 'use strict' on line 0, so the real code starts at line 1
JSFunction* func = JS_CompileUCFunction(m->m_cx, NULL, NULL, 0, NULL, reinterpret_cast<const jschar*> (codeUtf16.c_str()), (uintN)(codeUtf16.length()), fnAscii.c_str(), lineNo);
if (!func)
return false;
JS_AddRoot(m->m_cx, &func); // TODO: do we need to root this?
jsval scriptRval;
JSBool ok = JS_CallFunction(m->m_cx, NULL, func, 0, NULL, &scriptRval);
JS_RemoveRoot(m->m_cx, &func);
return ok ? true : false;
}
@@ -0,0 +1,59 @@
/* Copyright (C) 2010 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#include "lib/self_test.h"
#include "scriptinterface/ScriptInterface.h"
#include "ps/CLogger.h"
class TestScriptInterface : public CxxTest::TestSuite
{
public:
void test_loadscript_basic()
{
ScriptInterface script("Test");
TestLogger logger;
TS_ASSERT(script.LoadScript(L"test.js", L"var x = 1+1;"));
TS_ASSERT_WSTR_NOT_CONTAINS(logger.GetOutput(), L"JavaScript error");
TS_ASSERT_WSTR_NOT_CONTAINS(logger.GetOutput(), L"JavaScript warning");
}
void test_loadscript_error()
{
ScriptInterface script("Test");
TestLogger logger;
TS_ASSERT(!script.LoadScript(L"test.js", L"1+"));
TS_ASSERT_WSTR_CONTAINS(logger.GetOutput(), L"JavaScript error: test.js line 1\nSyntaxError: syntax error");
}
void test_loadscript_strict_warning()
{
ScriptInterface script("Test");
TestLogger logger;
TS_ASSERT(script.LoadScript(L"test.js", L"1+1;"));
TS_ASSERT_WSTR_CONTAINS(logger.GetOutput(), L"JavaScript warning: test.js line 1\nuseless expression");
}
void test_loadscript_strict_error()
{
ScriptInterface script("Test");
TestLogger logger;
TS_ASSERT(!script.LoadScript(L"test.js", L"with(1){}"));
TS_ASSERT_WSTR_CONTAINS(logger.GetOutput(), L"JavaScript error: test.js line 1\nSyntaxError: strict mode code may not contain \'with\' statements");
}
};