Chromium Code Reviews| Index: src/bootstrapper.cc |
| diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc |
| index 4bb0f4d0475ea21f6fb4a9cb0b611811800e068b..4b770897d05989cb409aba3a7d0bd0763ed2c55a 100644 |
| --- a/src/bootstrapper.cc |
| +++ b/src/bootstrapper.cc |
| @@ -168,6 +168,8 @@ class Genesis BASE_EMBEDDED { |
| Handle<JSFunction> CreateEmptyFunction(Isolate* isolate); |
| // Creates the ThrowTypeError function. ECMA 5th Ed. 13.2.3 |
| Handle<JSFunction> GetThrowTypeErrorFunction(); |
| + // Poison for sloppy generator function arguments/callee. |
| + Handle<JSFunction> GetGeneratorFunctionPoison(); |
| void CreateStrictModeFunctionMaps(Handle<JSFunction> empty); |
| @@ -303,6 +305,7 @@ class Genesis BASE_EMBEDDED { |
| Handle<Map> sloppy_function_map_writable_prototype_; |
| Handle<Map> strict_function_map_writable_prototype_; |
| Handle<JSFunction> throw_type_error_function; |
|
rossberg
2014/05/07 09:19:54
Nit: can we somehow rename this to make it more co
|
| + Handle<JSFunction> generator_function_poison; |
| BootstrapperActive active_; |
| friend class Bootstrapper; |
| @@ -585,6 +588,22 @@ Handle<JSFunction> Genesis::GetThrowTypeErrorFunction() { |
| } |
| +Handle<JSFunction> Genesis::GetGeneratorFunctionPoison() { |
| + if (generator_function_poison.is_null()) { |
| + Handle<String> name = factory()->InternalizeOneByteString( |
| + STATIC_ASCII_VECTOR("ThrowTypeError")); |
| + Handle<Code> code(isolate()->builtins()->builtin( |
| + Builtins::kGeneratorPoisonPill)); |
| + generator_function_poison = factory()->NewFunction(name, code); |
| + generator_function_poison->set_map(native_context()->sloppy_function_map()); |
| + generator_function_poison->shared()->DontAdaptArguments(); |
| + |
| + JSObject::PreventExtensions(generator_function_poison).Assert(); |
| + } |
| + return generator_function_poison; |
| +} |
| + |
| + |
| Handle<Map> Genesis::CreateStrictFunctionMap( |
| PrototypePropertyMode prototype_mode, |
| Handle<JSFunction> empty_function) { |
| @@ -633,6 +652,17 @@ static void SetAccessors(Handle<Map> map, |
| } |
| +static void ReplaceAccessors(Handle<Map> map, |
| + Handle<String> name, |
| + PropertyAttributes attributes, |
| + Handle<AccessorPair> accessor_pair) { |
| + DescriptorArray* descriptors = map->instance_descriptors(); |
| + int idx = descriptors->SearchWithCache(*name, *map); |
| + CallbacksDescriptor descriptor(name, accessor_pair, attributes); |
| + descriptors->Replace(idx, &descriptor); |
| +} |
| + |
| + |
| void Genesis::PoisonArgumentsAndCaller(Handle<Map> map) { |
| SetAccessors(map, factory()->arguments_string(), GetThrowTypeErrorFunction()); |
| SetAccessors(map, factory()->caller_string(), GetThrowTypeErrorFunction()); |
| @@ -1366,16 +1396,40 @@ void Genesis::InitializeExperimentalGlobal() { |
| // Create maps for generator functions and their prototypes. Store those |
| // maps in the native context. |
| - Handle<Map> function_map(native_context()->sloppy_function_map()); |
| - Handle<Map> generator_function_map = Map::Copy(function_map); |
| + Handle<Map> sloppy_function_map(native_context()->sloppy_function_map()); |
| + Handle<Map> generator_function_map = Map::Copy(sloppy_function_map); |
| generator_function_map->set_prototype(*generator_function_prototype); |
| native_context()->set_sloppy_generator_function_map( |
| *generator_function_map); |
| - Handle<Map> strict_mode_function_map( |
| - native_context()->strict_function_map()); |
| + // The "arguments" and "caller" instance properties aren't specified, so |
| + // technically we could leave them out. They make even less sense for |
| + // generators than for functions. Still, the same argument that it makes |
| + // sense to keep them around but poisoned in strict mode applies to |
| + // generators as well. With poisoned accessors, naive callers can still |
| + // iterate over the properties without accessing them. |
| + // |
| + // We can't use PoisonArgumentsAndCaller because that mutates accessor pairs |
| + // in place, and the initial state of the generator function map shares the |
| + // accessor pair with sloppy functions. Also the error message should be |
| + // different. Also unhappily, we can't use the API accessors to implement |
| + // poisoning, because API accessors present themselves as data properties, |
| + // not accessor properties, and so getOwnPropertyDescriptor raises an |
| + // exception as it tries to get the values. Sadness. |
| + Handle<AccessorPair> poison_pair(factory()->NewAccessorPair()); |
| + PropertyAttributes rw_attribs = |
| + static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE); |
| + poison_pair->set_getter(*GetGeneratorFunctionPoison()); |
| + poison_pair->set_setter(*GetGeneratorFunctionPoison()); |
| + ReplaceAccessors(generator_function_map, factory()->arguments_string(), |
| + rw_attribs, poison_pair); |
| + ReplaceAccessors(generator_function_map, factory()->caller_string(), |
| + rw_attribs, poison_pair); |
| + |
| + Handle<Map> strict_function_map(native_context()->strict_function_map()); |
| Handle<Map> strict_mode_generator_function_map = |
|
rossberg
2014/05/07 09:19:54
Nit: for consistency, drop _mode_ here, too.
|
| - Map::Copy(strict_mode_function_map); |
| + Map::Copy(strict_function_map); |
| + // "arguments" and "caller" already poisoned. |
| strict_mode_generator_function_map->set_prototype( |
| *generator_function_prototype); |
| native_context()->set_strict_generator_function_map( |