Make sure that the body of the function created by calling Function is

on a line of its own.  This allows the body to be terminated by a
single-line comment.

Also, make sure to set the name of the function to anonymous after the
fact so that recursion through the name anonymous is not allowed and
so that global variables called anonymous are not shadowed.

This is a fix for http://code.google.com/p/v8/issues/detail?id=85
Review URL: http://codereview.chromium.org/4248

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@370 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
ager@chromium.org 2008-09-25 07:35:45 +00:00
parent 222c7cd957
commit ff4e9ea134
7 changed files with 62 additions and 32 deletions

View File

@ -202,8 +202,9 @@ Handle<JSFunction> Compiler::Compile(Handle<String> source,
}
Handle<JSFunction> Compiler::CompileEval(bool is_global,
Handle<String> source) {
Handle<JSFunction> Compiler::CompileEval(Handle<String> source,
int line_offset,
bool is_global) {
Counters::total_eval_size.Increment(source->length());
Counters::total_compile_size.Increment(source->length());
@ -219,6 +220,7 @@ Handle<JSFunction> Compiler::CompileEval(bool is_global,
if (result.is_null()) {
// Create a script object describing the script to be compiled.
Handle<Script> script = Factory::NewScript(source);
script->set_line_offset(Smi::FromInt(line_offset));
result = MakeFunction(is_global, true, script, NULL, NULL);
if (!result.is_null()) {
CompilationCache::Associate(source, entry, result);

View File

@ -57,7 +57,9 @@ class Compiler : public AllStatic {
ScriptDataImpl* script_Data);
// Compile a String source within a context for Eval.
static Handle<JSFunction> CompileEval(bool is_global, Handle<String> source);
static Handle<JSFunction> CompileEval(Handle<String> source,
int line_offset,
bool is_global);
// Compile from function info (used for lazy compilation). Returns
// true on success and false if the compilation resulted in a stack

View File

@ -1230,7 +1230,7 @@ DebugCommandProcessor.prototype.scriptsCommandToJSONRequest_ = function(args) {
DebugCommandProcessor.prototype.responseToText = function(json_response) {
try {
// Convert the JSON string to an object.
response = %CompileString('(' + json_response + ')', false)();
response = %CompileString('(' + json_response + ')', 0, false)();
if (!response.success) {
return response.message;
@ -1436,7 +1436,7 @@ DebugCommandProcessor.prototype.processDebugJSONRequest = function(json_request,
try {
try {
// Convert the JSON string to an object.
request = %CompileString('(' + json_request + ')', false)();
request = %CompileString('(' + json_request + ')', 0, false)();
// Create an initial response.
response = this.createResponse(request);
@ -1889,7 +1889,7 @@ DebugCommandProcessor.prototype.scriptsRequest_ = function(request, response) {
DebugCommandProcessor.prototype.isRunning = function(json_response) {
try {
// Convert the JSON string to an object.
response = %CompileString('(' + json_response + ')', false)();
response = %CompileString('(' + json_response + ')', 0, false)();
// Return whether VM should be running after this request.
return response.running;

View File

@ -726,6 +726,17 @@ static Object* Runtime_FunctionGetName(Arguments args) {
}
static Object* Runtime_FunctionSetName(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 2);
CONVERT_CHECKED(JSFunction, f, args[0]);
CONVERT_CHECKED(String, name, args[1]);
f->shared()->set_name(name);
return Heap::undefined_value();
}
static Object* Runtime_FunctionGetScript(Arguments args) {
HandleScope scope;
ASSERT(args.length() == 1);
@ -3361,10 +3372,11 @@ static Object* Runtime_EvalReceiver(Arguments args) {
static Object* Runtime_CompileString(Arguments args) {
HandleScope scope;
ASSERT(args.length() == 2);
ASSERT(args.length() == 3);
CONVERT_ARG_CHECKED(String, source, 0);
bool contextual = args[1]->IsTrue();
RUNTIME_ASSERT(contextual || args[1]->IsFalse());
CONVERT_ARG_CHECKED(Smi, line_offset, 1);
bool contextual = args[2]->IsTrue();
RUNTIME_ASSERT(contextual || args[2]->IsFalse());
// Compute the eval context.
Handle<Context> context;
@ -3383,7 +3395,7 @@ static Object* Runtime_CompileString(Arguments args) {
// Compile source string.
bool is_global = context->IsGlobalContext();
Handle<JSFunction> boilerplate =
Compiler::CompileEval(is_global, source);
Compiler::CompileEval(source, line_offset->value(), is_global);
if (boilerplate.is_null()) return Failure::Exception();
Handle<JSFunction> fun =
Factory::NewFunctionFromBoilerplate(boilerplate, context);
@ -4502,7 +4514,7 @@ static Object* Runtime_DebugEvaluate(Arguments args) {
Factory::NewStringFromAscii(Vector<const char>(source_str,
source_str_length));
Handle<JSFunction> boilerplate =
Compiler::CompileEval(context->IsGlobalContext(), function_source);
Compiler::CompileEval(function_source, 0, context->IsGlobalContext());
if (boilerplate.is_null()) return Failure::Exception();
Handle<JSFunction> compiled_function =
Factory::NewFunctionFromBoilerplate(boilerplate, context);
@ -4558,7 +4570,7 @@ static Object* Runtime_DebugEvaluateGlobal(Arguments args) {
Handle<Context> context = Top::global_context();
// Compile the source to be evaluated.
Handle<JSFunction> boilerplate(Compiler::CompileEval(true, source));
Handle<JSFunction> boilerplate(Compiler::CompileEval(source, 0, true));
if (boilerplate.is_null()) return Failure::Exception();
Handle<JSFunction> compiled_function =
Handle<JSFunction>(Factory::NewFunctionFromBoilerplate(boilerplate,

View File

@ -157,6 +157,7 @@ namespace v8 { namespace internal {
F(FunctionSetLength, 2) \
F(FunctionSetPrototype, 2) \
F(FunctionGetName, 1) \
F(FunctionSetName, 2) \
F(FunctionGetSourceCode, 1) \
F(FunctionGetScript, 1) \
F(FunctionGetScriptSourcePosition, 1) \
@ -180,7 +181,7 @@ namespace v8 { namespace internal {
F(NumberIsFinite, 1) \
\
/* Globals */ \
F(CompileString, 2) \
F(CompileString, 3) \
F(CompileScript, 4) \
F(GlobalPrint, 1) \
\

View File

@ -201,7 +201,7 @@ $Object.prototype.constructor = $Object;
%AddProperty(global, "eval", function(x) {
if (!IS_STRING(x)) return x;
var f = %CompileString(x, true);
var f = %CompileString(x, 0, true);
if (!IS_FUNCTION(f)) return f;
return f.call(%EvalReceiver(this));
@ -212,7 +212,7 @@ $Object.prototype.constructor = $Object;
%AddProperty(global, "execScript", function(expr, lang) {
// NOTE: We don't care about the character casing.
if (!lang || /javascript/i.test(lang)) {
var f = %CompileString(ToString(expr), false);
var f = %CompileString(ToString(expr), 0, false);
f.call(global);
}
return null;
@ -406,11 +406,13 @@ function NewFunction(arg1) { // length == 1
if (p.indexOf(')') != -1) throw MakeSyntaxError('unable_to_parse',[]);
}
var body = (n > 0) ? ToString(%_Arguments(n - 1)) : '';
var source = '(function anonymous(' + p + ') { ' + body + ' })';
var source = '(function(' + p + ') {\n' + body + '\n})';
// The call to SetNewFunctionAttributes will ensure the prototype
// property of the resulting function is enumerable (ECMA262, 15.3.5.2).
return %SetNewFunctionAttributes(%CompileString(source, false)());
var f = %CompileString(source, -1, false)();
%FunctionSetName(f, "anonymous");
return %SetNewFunctionAttributes(f);
};
%SetCode($Function, NewFunction);

View File

@ -27,36 +27,47 @@
var f = Function();
assertTrue(typeof f() == 'undefined');
var f = new Function();
f = new Function();
assertTrue(typeof f() == 'undefined');
var f = Function('return 1');
f = Function('return 1');
assertEquals(1, f());
var f = new Function('return 1');
f = new Function('return 1');
assertEquals(1, f());
var f = Function('return true');
f = Function('return true');
assertTrue(f());
var f = new Function('return true');
f = new Function('return true');
assertTrue(f());
var f = Function('x', 'return x')
assertEquals(1, f(1));
assertEquals('bar', f('bar'));
assertTrue(typeof f() == 'undefined');
var x = {};
assertTrue(x === f(x));
var f = new Function('x', 'return x')
f = Function('x', 'return x');
assertEquals(1, f(1));
assertEquals('bar', f('bar'));
assertTrue(typeof f() == 'undefined');
var x = {};
assertTrue(x === f(x));
var f = Function('x', 'y', 'return x+y');
f = Function('x', 'return x // comment');
assertEquals(1, f(1));
f = Function('return typeof anonymous');
assertEquals('undefined', f());
var anonymous = 42;
f = Function('return anonymous;');
assertEquals(42, f());
f = new Function('x', 'return x')
assertEquals(1, f(1));
assertEquals('bar', f('bar'));
assertTrue(typeof f() == 'undefined');
var x = {};
assertTrue(x === f(x));
f = Function('x', 'y', 'return x+y');
assertEquals(5, f(2, 3));
assertEquals('foobar', f('foo', 'bar'));
var f = new Function('x', 'y', 'return x+y');
f = new Function('x', 'y', 'return x+y');
assertEquals(5, f(2, 3));
assertEquals('foobar', f('foo', 'bar'));
@ -66,7 +77,7 @@ var z = {}; z.toString = function() { return 'return x*y'; }
var f = Function(x, y, z);
assertEquals(25, f(5, 5));
assertEquals(42, f(2, 21));
var f = new Function(x, y, z);
f = new Function(x, y, z);
assertEquals(25, f(5, 5));
assertEquals(42, f(2, 21));