Coverage Report

Created: 2025-12-24 06:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/moddable/xs/sources/xsAll.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2016-2017  Moddable Tech, Inc.
3
 *
4
 *   This file is part of the Moddable SDK Runtime.
5
 * 
6
 *   The Moddable SDK Runtime is free software: you can redistribute it and/or modify
7
 *   it under the terms of the GNU Lesser General Public License as published by
8
 *   the Free Software Foundation, either version 3 of the License, or
9
 *   (at your option) any later version.
10
 * 
11
 *   The Moddable SDK Runtime is distributed in the hope that it will be useful,
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *   GNU Lesser General Public License for more details.
15
 * 
16
 *   You should have received a copy of the GNU Lesser General Public License
17
 *   along with the Moddable SDK Runtime.  If not, see <http://www.gnu.org/licenses/>.
18
 *
19
 * This file incorporates work covered by the following copyright and  
20
 * permission notice:  
21
 *
22
 *       Copyright (C) 2010-2016 Marvell International Ltd.
23
 *       Copyright (C) 2002-2010 Kinoma, Inc.
24
 *
25
 *       Licensed under the Apache License, Version 2.0 (the "License");
26
 *       you may not use this file except in compliance with the License.
27
 *       You may obtain a copy of the License at
28
 *
29
 *        http://www.apache.org/licenses/LICENSE-2.0
30
 *
31
 *       Unless required by applicable law or agreed to in writing, software
32
 *       distributed under the License is distributed on an "AS IS" BASIS,
33
 *       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34
 *       See the License for the specific language governing permissions and
35
 *       limitations under the License.
36
 */
37
38
#define _GNU_SOURCE
39
#include "xsAll.h"
40
#if mxMacOSX || mxLinux
41
#include <dlfcn.h>
42
#endif
43
44
static void fxBufferFunctionNameAddress(txMachine* the, txString buffer, txSize size, txID id, txCallback address, txID profileID);
45
static void fxBufferName(txString dst, txString src, txSize size);
46
47
txString fxAdornStringC(txMachine* the, txString prefix, txSlot* string, txString suffix)
48
507k
{
49
507k
  txSize stringSize = mxStringLength(string->value.string);
50
507k
  txSize prefixSize = prefix ? mxStringLength(prefix) : 0;
51
507k
  txSize suffixSize = suffix ? mxStringLength(suffix) : 0;
52
507k
  txSize resultSize = fxAddChunkSizes(the, fxAddChunkSizes(the, fxAddChunkSizes(the, stringSize, prefixSize), suffixSize), 1);
53
507k
  txString result = (txString)fxNewChunk(the, resultSize);
54
507k
  if (prefix && prefixSize)
55
507k
    c_memcpy(result, prefix, prefixSize);
56
507k
  if (stringSize)
57
507k
    c_memcpy(result + prefixSize, string->value.string, stringSize);
58
507k
  if (suffix && suffixSize)
59
160k
    c_memcpy(result + prefixSize + stringSize, suffix, suffixSize);
60
507k
  result[prefixSize + stringSize + suffixSize] = 0;
61
507k
  string->kind = XS_STRING_KIND;
62
507k
  string->value.string = result;
63
507k
  return result;
64
507k
}
65
66
txSlot* fxArgToCallback(txMachine* the, txInteger argi)
67
0
{
68
0
  if (mxArgc > argi) {
69
0
    txSlot* slot = mxArgv(argi);
70
0
    if (slot->kind == XS_REFERENCE_KIND) {
71
0
      txSlot* instance = slot->value.reference;
72
0
again:
73
0
      if (instance) {
74
0
        txSlot* exotic = instance->next;
75
0
        if (exotic && (exotic->flag & XS_INTERNAL_FLAG)) {
76
0
          if (((exotic->kind == XS_CALLBACK_KIND) || (exotic->kind == XS_CALLBACK_X_KIND) || (exotic->kind == XS_CODE_KIND) || (exotic->kind == XS_CODE_X_KIND)))
77
0
            return slot;
78
0
          if (exotic->kind == XS_PROXY_KIND) {
79
0
            instance = exotic->value.proxy.target;
80
0
            goto again;
81
0
          }
82
0
        }
83
0
      }
84
0
    }
85
#if mxHostFunctionPrimitive
86
    if (slot->kind == XS_HOST_FUNCTION_KIND)
87
      return slot;
88
#endif
89
0
  }
90
0
  mxTypeError("callback: not a function");
91
0
  return C_NULL;
92
0
}
93
94
void fxBufferFrameName(txMachine* the, txString buffer, txSize size, txSlot* frame, txString suffix)
95
4.99k
{
96
4.99k
  txSlot* target = frame + 2; 
97
4.99k
  txSlot* function = frame + 3; 
98
4.99k
  txSlot* _this = frame + 4;
99
4.99k
  if (function->kind == XS_REFERENCE_KIND) {
100
4.99k
    function = function->value.reference;
101
4.99k
    if (mxIsFunction(function)) {
102
4.99k
      if (target->kind == XS_UNDEFINED_KIND) {
103
4.99k
        txSlot* home = mxFunctionInstanceHome(function)->value.home.object;
104
4.99k
        if (home) {
105
4.99k
          if (mxIsFunction(home)) {
106
0
            fxBufferFunctionName(the, buffer, size, home, ".");
107
0
          }
108
4.99k
          else {
109
4.99k
            txSlot* constructor = mxBehaviorGetProperty(the, home, mxID(_constructor), 0, XS_OWN);
110
4.99k
            if (constructor) {
111
0
              if (constructor->kind == XS_REFERENCE_KIND) {
112
0
                constructor = constructor->value.reference;
113
0
                if (mxIsFunction(constructor))
114
0
                  fxBufferFunctionName(the, buffer, size, constructor, ".prototype.");
115
0
              }
116
0
            }
117
4.99k
            else if (_this->kind == XS_REFERENCE_KIND) {
118
4.99k
              fxBufferObjectName(the, buffer, size, _this->value.reference, ".");
119
4.99k
            }
120
4.99k
          }
121
4.99k
        }
122
4.99k
      }
123
4.99k
      fxBufferFunctionName(the, buffer, size, function, "");
124
4.99k
    }
125
4.99k
  }
126
#if mxHostFunctionPrimitive
127
  else if (function->kind == XS_HOST_FUNCTION_KIND) {
128
    fxBufferFunctionNameAddress(the, buffer, size, function->value.hostFunction.builder->id, function->value.hostFunction.builder->callback, function->value.hostFunction.profileID);
129
  }
130
#endif
131
0
  else
132
0
    c_strncat(buffer, "(host)", size - mxStringLength(buffer) - 1);
133
4.99k
  c_strncat(buffer, suffix, size - mxStringLength(buffer) - 1);
134
4.99k
}
135
136
void fxBufferFunctionName(txMachine* the, txString buffer, txSize size, txSlot* function, txString suffix)
137
4.99k
{
138
4.99k
  txSlot* slot = mxFunctionInstanceCode(function);
139
4.99k
  txSlot* home = mxFunctionInstanceHome(function);
140
4.99k
  if ((slot->kind == XS_CODE_KIND) || (slot->kind == XS_CODE_X_KIND))
141
0
    fxBufferFunctionNameAddress(the, buffer, size, slot->ID, C_NULL, home->ID);
142
4.99k
  else
143
4.99k
    fxBufferFunctionNameAddress(the, buffer, size, slot->ID, slot->value.callback.address, home->ID);
144
4.99k
    c_strncat(buffer, suffix, size - mxStringLength(buffer) - 1);
145
4.99k
}
146
147
void fxBufferFunctionNameAddress(txMachine* the, txString buffer, txSize size, txID id, txCallback address, txID profileID)
148
4.99k
{
149
4.99k
  txInteger length;
150
4.99k
  if (id != XS_NO_ID) {
151
4.99k
    txBoolean adorn;
152
4.99k
    txString string = fxGetKeyString(the, id, &adorn);
153
4.99k
    if (adorn)
154
0
      c_strncat(buffer, "[", size - mxStringLength(buffer) - 1);
155
4.99k
    fxBufferName(buffer, string, size - mxStringLength(buffer) - 1);
156
4.99k
    if (adorn)
157
0
      c_strncat(buffer, "]", size - mxStringLength(buffer) - 1);
158
4.99k
    return;
159
4.99k
  }
160
0
  if (address) {
161
0
    c_strncat(buffer, "@", size - mxStringLength(buffer) - 1);
162
0
#if mxMacOSX || mxLinux
163
0
    Dl_info info;
164
0
    if (dladdr(address, &info) && info.dli_sname)
165
0
      c_strncat(buffer, info.dli_sname, size - mxStringLength(buffer) - 1);
166
0
    else 
167
0
#endif
168
0
    {
169
0
      c_strncat(buffer, "anonymous-", size - mxStringLength(buffer) - 1);
170
0
      length = mxStringLength(buffer);
171
0
      fxIntegerToString(the, profileID, buffer + length, size - length - 1);
172
0
    }
173
0
  }
174
0
  else {
175
0
    c_strncat(buffer, "(anonymous-", size - mxStringLength(buffer) - 1);
176
0
    length = mxStringLength(buffer);
177
0
    fxIntegerToString(the, profileID, buffer + length, size - length - 1);
178
0
    c_strncat(buffer, ")", size - mxStringLength(buffer) - 1);
179
0
  }
180
0
}
181
182
void fxBufferObjectName(txMachine* the, txString buffer, txSize size, txSlot* object, txString suffix)
183
4.99k
{
184
4.99k
  txSlot* slot = mxBehaviorGetProperty(the, object, mxID(_Symbol_toStringTag), 0, XS_ANY);
185
4.99k
  if (slot && ((slot->kind == XS_STRING_KIND) || (slot->kind == XS_STRING_X_KIND)) && !c_isEmpty(slot->value.string)) {
186
4.99k
    fxBufferName(buffer, slot->value.string, size - mxStringLength(buffer) - 1);
187
4.99k
    c_strncat(buffer, suffix, size - mxStringLength(buffer) - 1);
188
4.99k
  }
189
4.99k
}
190
191
void fxBufferName(txString dst, txString src, txSize size)
192
9.98k
{
193
9.98k
  dst += mxStringLength(dst);
194
54.9k
  for (;;) {
195
54.9k
    txInteger c;
196
54.9k
    txSize length;
197
54.9k
    src = mxStringByteDecode(src, &c);
198
54.9k
    if (c == C_EOF)
199
9.98k
      break;
200
44.9k
    length = mxStringByteLength(c);
201
44.9k
    if (length > size)
202
0
      break;
203
44.9k
    dst = mxStringByteEncode(dst, c);
204
44.9k
    size -= length;
205
44.9k
  }
206
9.98k
  *dst = 0;
207
9.98k
}
208
209
txString fxConcatString(txMachine* the, txSlot* a, txSlot* b)
210
0
{
211
0
  txSize aSize = mxStringLength(a->value.string);
212
0
  txSize bSize = mxStringLength(b->value.string);
213
0
  txSize resultSize = fxAddChunkSizes(the, fxAddChunkSizes(the, aSize, bSize), 1);
214
0
  txString result = (txString)fxNewChunk(the, resultSize);
215
0
  c_memcpy(result, a->value.string, aSize);
216
0
  c_memcpy(result + aSize, b->value.string, bSize + 1);
217
0
  a->value.string = result;
218
0
  a->kind = XS_STRING_KIND;
219
0
  return result;
220
0
}
221
222
txString fxConcatStringC(txMachine* the, txSlot* a, txString b)
223
0
{
224
0
  txSize aSize = mxStringLength(a->value.string);
225
0
  txSize bSize = mxStringLength(b);
226
0
  txSize resultSize = fxAddChunkSizes(the, fxAddChunkSizes(the, aSize, bSize), 1);
227
0
  txString result = C_NULL;
228
0
  if (a->kind == XS_STRING_KIND)
229
0
    result = (txString)fxRenewChunk(the, a->value.string, resultSize);
230
0
  if (!result) {
231
0
    result = (txString)fxNewChunk(the, resultSize);
232
0
    c_memcpy(result, a->value.string, aSize);
233
0
    a->value.string = result;
234
0
    a->kind = XS_STRING_KIND;
235
0
  }
236
0
  c_memcpy(result + aSize, b, bSize + 1);
237
0
  return result;
238
0
}
239
240
txString fxCopyString(txMachine* the, txSlot* a, txSlot* b)
241
0
{
242
0
  txString result = b->value.string;
243
0
  a->value.string = result;
244
0
  a->kind = b->kind;
245
0
  return result;
246
0
}
247
248
txString fxCopyStringC(txMachine* the, txSlot* a, txString b)
249
525k
{
250
525k
  txSize bSize = mxStringLength(b);
251
525k
  txSize resultSize = fxAddChunkSizes(the, bSize, 1);
252
525k
  txString result = (txString)fxNewChunk(the, resultSize);
253
525k
  c_memcpy(result, b, resultSize);
254
525k
  a->value.string = result;
255
525k
  a->kind = XS_STRING_KIND;
256
525k
  return result;
257
525k
}
258
259
txBoolean fxIsCanonicalIndex(txMachine* the, txID id)
260
0
{
261
0
  txSlot* key = fxGetKey(the, id);
262
0
  if (key->flag & XS_DONT_ENUM_FLAG) {
263
0
    txString string = key->value.key.string;
264
0
    char buffer[256], c;
265
0
    txNumber number;
266
0
    c = c_read8(string);
267
0
    if (('+' != c) && ('-' != c) && ('.' != c) && ('I' != c) && ('N' != c) && !(('0' <= c) && ('9' >= c)))
268
0
      return 0;
269
0
    number = fxStringToNumber(the, string, 1);
270
0
    if (number == -0)
271
0
      return 1;
272
0
    fxNumberToString(the, number, buffer, sizeof(buffer), 0, 0);
273
0
    if (!c_strcmp(string, buffer)) {
274
0
      return 1;
275
0
    }
276
0
  }
277
0
  return 0;
278
0
}
279
280
int fxStringGetter(void* theStream)
281
0
{
282
0
  txStringStream* aStream = (txStringStream*)theStream;
283
0
  int result = C_EOF;
284
  
285
0
  if (aStream->offset < aStream->size) {
286
0
    result = *(aStream->slot->value.string + aStream->offset);
287
0
    aStream->offset++;
288
0
  }
289
0
  return result;
290
0
}
291
292
int fxStringCGetter(void* theStream)
293
0
{
294
0
  txStringCStream* aStream = (txStringCStream*)theStream;
295
0
  int result = C_EOF;
296
  
297
0
  if (aStream->offset < aStream->size) {
298
0
    result = *(aStream->buffer + aStream->offset);
299
0
    aStream->offset++;
300
0
  }
301
0
  return result;
302
0
}
303
304
void fxJump(txMachine* the)
305
4.99k
{
306
4.99k
  txJump* aJump = the->firstJump;
307
4.99k
  c_longjmp(aJump->buffer, 1);
308
4.99k
}