Bug 1083913: Add a 'columnNumber' parameter to the JS shell's 'evaluate' and 'offThreadCompileScript' functions. r=shu

This commit is contained in:
Jim Blandy 2014-11-12 14:51:41 -08:00
parent 53c73dd1e7
commit f5e193968c
7 changed files with 84 additions and 1 deletions

View File

@ -538,6 +538,9 @@ Parser<ParseHandler>::checkOptions()
checkOptionsCalled = true;
#endif
if (!tokenStream.checkOptions())
return false;
return true;
}

View File

@ -8,6 +8,7 @@
#include "frontend/TokenStream.h"
#include "mozilla/IntegerTypeTraits.h"
#include "mozilla/PodOperations.h"
#include "mozilla/UniquePtr.h"
@ -341,6 +342,19 @@ TokenStream::TokenStream(ExclusiveContext *cx, const ReadOnlyCompileOptions &opt
#pragma warning(pop)
#endif
bool
TokenStream::checkOptions()
{
// Constrain starting columns to half of the range of a signed 32-bit value,
// to avoid overflow.
if (options().column >= mozilla::MaxValue<int32_t>::value / 2 + 1) {
reportErrorNoOffset(JSMSG_BAD_COLUMN_NUMBER);
return false;
}
return true;
}
TokenStream::~TokenStream()
{
}
@ -737,6 +751,17 @@ TokenStream::reportError(unsigned errorNumber, ...)
return result;
}
bool
TokenStream::reportErrorNoOffset(unsigned errorNumber, ...)
{
va_list args;
va_start(args, errorNumber);
bool result = reportCompileErrorNumberVA(NoOffset, JSREPORT_ERROR, errorNumber,
args);
va_end(args);
return result;
}
bool
TokenStream::reportWarning(unsigned errorNumber, ...)
{

View File

@ -258,6 +258,8 @@ class MOZ_STACK_CLASS TokenStream
~TokenStream();
bool checkOptions();
// Accessors.
const Token &currentToken() const { return tokens[cursor]; }
bool isCurrentTokenType(TokenKind type) const {
@ -289,6 +291,7 @@ class MOZ_STACK_CLASS TokenStream
// TokenStream-specific error reporters.
bool reportError(unsigned errorNumber, ...);
bool reportErrorNoOffset(unsigned errorNumber, ...);
bool reportWarning(unsigned errorNumber, ...);
static const uint32_t NoOffset = UINT32_MAX;

View File

@ -0,0 +1,40 @@
// Simple tests for evaluate's "columnNumber" option.
load(libdir + 'asserts.js');
assertEq(evaluate("saveStack().column"), 0);
assertEq(evaluate("saveStack().column", { columnNumber: 1729 }), 1729);
assertEq(evaluate("\nsaveStack().column", { columnNumber: 1729 }), 0);
assertEq(evaluate("saveStack().column", { columnNumber: "42" }), 42);
assertThrowsInstanceOf(() => evaluate("saveStack().column", { columnNumber: -10 }),
RangeError);
assertThrowsInstanceOf(() => evaluate("saveStack().column", { columnNumber: Math.pow(2,30) }),
RangeError);
if (helperThreadCount() > 0) {
print("offThreadCompileScript 1");
offThreadCompileScript("saveStack().column", { columnNumber: -10 });
assertThrowsInstanceOf(runOffThreadScript, RangeError);
print("offThreadCompileScript 2");
offThreadCompileScript("saveStack().column", { columnNumber: Math.pow(2,30) });
assertThrowsInstanceOf(runOffThreadScript, RangeError);
print("offThreadCompileScript 3");
offThreadCompileScript("saveStack().column", { columnNumber: 10000 });
assertEq(runOffThreadScript(), 10000);
}
// Check handling of columns near the limit of our ability to represent them.
// (This is hardly thorough, but since web content can't set column numbers,
// it's probably not worth it to be thorough.)
const maxColumn = Math.pow(2, 22) - 1;
assertEq(evaluate("saveStack().column", { columnNumber: maxColumn }),
maxColumn);
assertEq(evaluate("saveStack().column", { columnNumber: maxColumn + 1 }),
0);
// Check the 'silently zero' behavior when we reach the limit of the srcnotes
// column encoding.
assertEq(evaluate(" saveStack().column", { columnNumber: maxColumn }),
0);

View File

@ -316,6 +316,7 @@ MSG_DEF(JSMSG_VAR_HIDES_ARG, 1, JSEXN_TYPEERR, "variable {0} redeclare
MSG_DEF(JSMSG_WHILE_AFTER_DO, 0, JSEXN_SYNTAXERR, "missing while after do-loop body")
MSG_DEF(JSMSG_YIELD_IN_ARROW, 0, JSEXN_SYNTAXERR, "arrow function may not contain yield")
MSG_DEF(JSMSG_YIELD_IN_DEFAULT, 0, JSEXN_SYNTAXERR, "yield in default expression")
MSG_DEF(JSMSG_BAD_COLUMN_NUMBER, 0, JSEXN_RANGEERR, "column number out of range")
// asm.js
MSG_DEF(JSMSG_USE_ASM_TYPE_FAIL, 1, JSEXN_TYPEERR, "asm.js type error: {0}")

View File

@ -940,6 +940,15 @@ ParseCompileOptions(JSContext *cx, CompileOptions &options, HandleObject opts,
options.setLine(u);
}
if (!JS_GetProperty(cx, opts, "columnNumber", &v))
return false;
if (!v.isUndefined()) {
int32_t c;
if (!ToInt32(cx, v, &c))
return false;
options.setColumn(c);
}
if (!JS_GetProperty(cx, opts, "sourceIsLazy", &v))
return false;
if (v.isBoolean())
@ -4259,6 +4268,7 @@ static const JSFunctionSpecWithHelp shell_functions[] = {
" noScriptRval: use the no-script-rval compiler option (default: false)\n"
" fileName: filename for error messages and debug info\n"
" lineNumber: starting line number for error messages and debug info\n"
" columnNumber: starting column number for error messages and debug info\n"
" global: global in which to execute the code\n"
" newContext: if true, create and use a new cx (default: false)\n"
" saveFrameChain: if true, save the frame chain before evaluating code\n"
@ -4463,6 +4473,7 @@ static const JSFunctionSpecWithHelp shell_functions[] = {
" noScriptRval: use the no-script-rval compiler option (default: false)\n"
" fileName: filename for error messages and debug info\n"
" lineNumber: starting line number for error messages and debug info\n"
" columnNumber: starting column number for error messages and debug info\n"
" element: if present with value |v|, convert |v| to an object |o| and\n"
" mark the source as being attached to the DOM element |o|. If the\n"
" property is omitted or |v| is null, don't attribute the source to\n"

View File

@ -34,7 +34,7 @@ namespace js {
* Nightly) and without (all others). FIXME: Bug 1066322 - Enable ES6 symbols
* in all builds.
*/
static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 200;
static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 202;
static_assert(XDR_BYTECODE_VERSION_SUBTRAHEND % 2 == 0, "see the comment above");
static const uint32_t XDR_BYTECODE_VERSION =
uint32_t(0xb973c0de - (XDR_BYTECODE_VERSION_SUBTRAHEND