forked from mirrors/0ad
# Compile gameplay scripts in strict mode.
Fixes #487. This was SVN commit r7456.
This commit is contained in:
@@ -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");
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user