v8/src/apinatives.js
wingo@igalia.com 558a05bfcf Fix symbol-named function template properties in the API
Thanks to Yutaka Hirano <yhirano@chromium.org> for finding the bug and
providing the test case.

R=rossberg@chromium.org
BUG=

Review URL: https://codereview.chromium.org/496663002

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23269 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
2014-08-21 11:55:46 +00:00

120 lines
4.0 KiB
JavaScript

// Copyright 2006-2008 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
"use strict";
// This file contains infrastructure used by the API. See
// v8natives.js for an explanation of these files are processed and
// loaded.
function CreateDate(time) {
var date = new $Date();
date.setTime(time);
return date;
}
var kApiFunctionCache = new InternalArray();
var functionCache = kApiFunctionCache;
function Instantiate(data, name) {
if (!%IsTemplate(data)) return data;
var tag = %GetTemplateField(data, kApiTagOffset);
switch (tag) {
case kFunctionTag:
return InstantiateFunction(data, name);
case kNewObjectTag:
var Constructor = %GetTemplateField(data, kApiConstructorOffset);
// Note: Do not directly use a function template as a condition, our
// internal ToBoolean doesn't handle that!
var result;
if (typeof Constructor === 'undefined') {
result = {};
ConfigureTemplateInstance(result, data);
} else {
// ConfigureTemplateInstance is implicitly called before calling the API
// constructor in HandleApiCall.
result = new (Instantiate(Constructor))();
result = %ToFastProperties(result);
}
return result;
default:
throw 'Unknown API tag <' + tag + '>';
}
}
function InstantiateFunction(data, name) {
// We need a reference to kApiFunctionCache in the stack frame
// if we need to bail out from a stack overflow.
var cache = kApiFunctionCache;
var serialNumber = %GetTemplateField(data, kApiSerialNumberOffset);
var isFunctionCached =
(serialNumber in cache) && (cache[serialNumber] != kUninitialized);
if (!isFunctionCached) {
try {
var flags = %GetTemplateField(data, kApiFlagOffset);
var prototype;
if (!(flags & (1 << kRemovePrototypeBit))) {
var template = %GetTemplateField(data, kApiPrototypeTemplateOffset);
prototype = typeof template === 'undefined'
? {} : Instantiate(template);
var parent = %GetTemplateField(data, kApiParentTemplateOffset);
// Note: Do not directly use a function template as a condition, our
// internal ToBoolean doesn't handle that!
if (typeof parent !== 'undefined') {
var parent_fun = Instantiate(parent);
%InternalSetPrototype(prototype, parent_fun.prototype);
}
}
var fun = %CreateApiFunction(data, prototype);
if (IS_STRING(name)) %FunctionSetName(fun, name);
var doNotCache = flags & (1 << kDoNotCacheBit);
if (!doNotCache) cache[serialNumber] = fun;
ConfigureTemplateInstance(fun, data);
if (doNotCache) return fun;
} catch (e) {
cache[serialNumber] = kUninitialized;
throw e;
}
}
return cache[serialNumber];
}
function ConfigureTemplateInstance(obj, data) {
var properties = %GetTemplateField(data, kApiPropertyListOffset);
if (!properties) return;
// Disable access checks while instantiating the object.
var requires_access_checks = %DisableAccessChecks(obj);
try {
for (var i = 1; i < properties[0];) {
var length = properties[i];
if (length == 3) {
var name = properties[i + 1];
var prop_data = properties[i + 2];
var attributes = properties[i + 3];
var value = Instantiate(prop_data, name);
%AddPropertyForTemplate(obj, name, value, attributes);
} else if (length == 4 || length == 5) {
// TODO(verwaest): The 5th value used to be access_control. Remove once
// the bindings are updated.
var name = properties[i + 1];
var getter = properties[i + 2];
var setter = properties[i + 3];
var attribute = properties[i + 4];
%DefineApiAccessorProperty(obj, name, getter, setter, attribute);
} else {
throw "Bad properties array";
}
i += length + 1;
}
} finally {
if (requires_access_checks) %EnableAccessChecks(obj);
}
}