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;
34      if (typeof Constructor === 'undefined') {
35        result = {};
36        ConfigureTemplateInstance(result, data);
37      } else {
38        // ConfigureTemplateInstance is implicitly called before calling the API
39        // constructor in HandleApiCall.
40        result = new (Instantiate(Constructor))();
41        result = %ToFastProperties(result);
42      }
43      return result;
44    default:
45      throw 'Unknown API tag <' + tag + '>';
46  }
47}
48
49
50function InstantiateFunction(data, name) {
51  // We need a reference to kApiFunctionCache in the stack frame
52  // if we need to bail out from a stack overflow.
53  var cache = kApiFunctionCache;
54  var serialNumber = %GetTemplateField(data, kApiSerialNumberOffset);
55  var isFunctionCached =
56   (serialNumber in cache) && (cache[serialNumber] != kUninitialized);
57  if (!isFunctionCached) {
58    try {
59      var flags = %GetTemplateField(data, kApiFlagOffset);
60      var prototype;
61      if (!(flags & (1 << kRemovePrototypeBit))) {
62        var template = %GetTemplateField(data, kApiPrototypeTemplateOffset);
63        prototype = typeof template === 'undefined'
64            ?  {} : Instantiate(template);
65
66        var parent = %GetTemplateField(data, kApiParentTemplateOffset);
67        // Note: Do not directly use a function template as a condition, our
68        // internal ToBoolean doesn't handle that!
69        if (typeof parent !== 'undefined') {
70          var parent_fun = Instantiate(parent);
71          %InternalSetPrototype(prototype, parent_fun.prototype);
72        }
73      }
74      var fun = %CreateApiFunction(data, prototype);
75      if (IS_STRING(name)) %FunctionSetName(fun, name);
76      var doNotCache = flags & (1 << kDoNotCacheBit);
77      if (!doNotCache) cache[serialNumber] = fun;
78      ConfigureTemplateInstance(fun, data);
79      if (doNotCache) return fun;
80    } catch (e) {
81      cache[serialNumber] = kUninitialized;
82      throw e;
83    }
84  }
85  return cache[serialNumber];
86}
87
88
89function ConfigureTemplateInstance(obj, data) {
90  var properties = %GetTemplateField(data, kApiPropertyListOffset);
91  if (!properties) return;
92  // Disable access checks while instantiating the object.
93  var requires_access_checks = %DisableAccessChecks(obj);
94  try {
95    for (var i = 1; i < properties[0];) {
96      var length = properties[i];
97      if (length == 3) {
98        var name = properties[i + 1];
99        var prop_data = properties[i + 2];
100        var attributes = properties[i + 3];
101        var value = Instantiate(prop_data, name);
102        %AddPropertyForTemplate(obj, name, value, attributes);
103      } else if (length == 4 || length == 5) {
104        // TODO(verwaest): The 5th value used to be access_control. Remove once
105        // the bindings are updated.
106        var name = properties[i + 1];
107        var getter = properties[i + 2];
108        var setter = properties[i + 3];
109        var attribute = properties[i + 4];
110        %DefineApiAccessorProperty(obj, name, getter, setter, attribute);
111      } else {
112        throw "Bad properties array";
113      }
114      i += length + 1;
115    }
116  } finally {
117    if (requires_access_checks) %EnableAccessChecks(obj);
118  }
119}
120