1// Copyright 2006-2008 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5"use strict";
6
7// This file contains infrastructure used by the API.  See
8// v8natives.js for an explanation of these files are processed and
9// loaded.
10
11
12function CreateDate(time) {
13  var date = new $Date();
14  date.setTime(time);
15  return date;
16}
17
18
19var kApiFunctionCache = new InternalArray();
20var functionCache = kApiFunctionCache;
21
22
23function Instantiate(data, name) {
24  if (!%IsTemplate(data)) return data;
25  var tag = %GetTemplateField(data, kApiTagOffset);
26  switch (tag) {
27    case kFunctionTag:
28      return InstantiateFunction(data, name);
29    case kNewObjectTag:
30      var Constructor = %GetTemplateField(data, kApiConstructorOffset);
31      // Note: Do not directly use a function template as a condition, our
32      // internal ToBoolean doesn't handle that!
33      var result = typeof Constructor === 'undefined' ?
34          {} : new (Instantiate(Constructor))();
35      ConfigureTemplateInstance(result, data);
36      result = %ToFastProperties(result);
37      return result;
38    default:
39      throw 'Unknown API tag <' + tag + '>';
40  }
41}
42
43
44function InstantiateFunction(data, name) {
45  // We need a reference to kApiFunctionCache in the stack frame
46  // if we need to bail out from a stack overflow.
47  var cache = kApiFunctionCache;
48  var serialNumber = %GetTemplateField(data, kApiSerialNumberOffset);
49  var isFunctionCached =
50   (serialNumber in cache) && (cache[serialNumber] != kUninitialized);
51  if (!isFunctionCached) {
52    try {
53      var flags = %GetTemplateField(data, kApiFlagOffset);
54      var prototype;
55      if (!(flags & (1 << kRemovePrototypeBit))) {
56        var template = %GetTemplateField(data, kApiPrototypeTemplateOffset);
57        prototype = typeof template === 'undefined'
58            ?  {} : Instantiate(template);
59
60        var parent = %GetTemplateField(data, kApiParentTemplateOffset);
61        // Note: Do not directly use a function template as a condition, our
62        // internal ToBoolean doesn't handle that!
63        if (typeof parent !== 'undefined') {
64          var parent_fun = Instantiate(parent);
65          %SetPrototype(prototype, parent_fun.prototype);
66        }
67      }
68      var fun = %CreateApiFunction(data, prototype);
69      if (name) %FunctionSetName(fun, name);
70      var doNotCache = flags & (1 << kDoNotCacheBit);
71      if (!doNotCache) cache[serialNumber] = fun;
72      ConfigureTemplateInstance(fun, data);
73      if (doNotCache) return fun;
74    } catch (e) {
75      cache[serialNumber] = kUninitialized;
76      throw e;
77    }
78  }
79  return cache[serialNumber];
80}
81
82
83function ConfigureTemplateInstance(obj, data) {
84  var properties = %GetTemplateField(data, kApiPropertyListOffset);
85  if (!properties) return;
86  // Disable access checks while instantiating the object.
87  var requires_access_checks = %DisableAccessChecks(obj);
88  try {
89    for (var i = 1; i < properties[0];) {
90      var length = properties[i];
91      if (length == 3) {
92        var name = properties[i + 1];
93        var prop_data = properties[i + 2];
94        var attributes = properties[i + 3];
95        var value = Instantiate(prop_data, name);
96        %SetProperty(obj, name, value, attributes);
97      } else if (length == 5) {
98        var name = properties[i + 1];
99        var getter = properties[i + 2];
100        var setter = properties[i + 3];
101        var attribute = properties[i + 4];
102        var access_control = properties[i + 5];
103        %SetAccessorProperty(
104            obj, name, getter, setter, attribute, access_control);
105      } else {
106        throw "Bad properties array";
107      }
108      i += length + 1;
109    }
110  } finally {
111    if (requires_access_checks) %EnableAccessChecks(obj);
112  }
113}
114