Coverage Report

Created: 2026-08-14 06:19

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
2.88M
{
49
2.88M
  txSize stringSize = mxStringLength(string->value.string);
50
2.88M
  txSize prefixSize = prefix ? mxStringLength(prefix) : 0;
51
2.88M
  txSize suffixSize = suffix ? mxStringLength(suffix) : 0;
52
2.88M
  txSize resultSize = fxAddChunkSizes(the, fxAddChunkSizes(the, fxAddChunkSizes(the, stringSize, prefixSize), suffixSize), 1);
53
2.88M
  txString result = (txString)fxNewChunk(the, resultSize);
54
2.88M
  if (prefix && prefixSize)
55
2.88M
    c_memcpy(result, prefix, prefixSize);
56
2.88M
  if (stringSize)
57
2.88M
    c_memcpy(result + prefixSize, string->value.string, stringSize);
58
2.88M
  if (suffix && suffixSize)
59
809k
    c_memcpy(result + prefixSize + stringSize, suffix, suffixSize);
60
2.88M
  result[prefixSize + stringSize + suffixSize] = 0;
61
2.88M
  string->kind = XS_STRING_KIND;
62
2.88M
  string->value.string = result;
63
2.88M
  return result;
64
2.88M
}
65
66
txSlot* fxArgToCallback(txMachine* the, txInteger argi)
67
332k
{
68
332k
  if (mxArgc > argi) {
69
332k
    txSlot* slot = mxArgv(argi);
70
332k
    if (slot->kind == XS_REFERENCE_KIND) {
71
332k
      txSlot* instance = slot->value.reference;
72
332k
again:
73
332k
      if (instance) {
74
332k
        txSlot* exotic = instance->next;
75
332k
        if (exotic && (exotic->flag & XS_INTERNAL_FLAG)) {
76
331k
          if (((exotic->kind == XS_CALLBACK_KIND) || (exotic->kind == XS_CALLBACK_X_KIND) || (exotic->kind == XS_CODE_KIND) || (exotic->kind == XS_CODE_X_KIND)))
77
331k
            return slot;
78
15
          if (exotic->kind == XS_PROXY_KIND) {
79
0
            instance = exotic->value.proxy.target;
80
0
            goto again;
81
0
          }
82
15
        }
83
332k
      }
84
332k
    }
85
#if mxHostFunctionPrimitive
86
    if (slot->kind == XS_HOST_FUNCTION_KIND)
87
      return slot;
88
#endif
89
332k
  }
90
332k
  mxTypeError("callback: not a function");
91
0
  return C_NULL;
92
332k
}
93
94
void fxBufferFrameName(txMachine* the, txString buffer, txSize size, txSlot* frame, txString suffix)
95
1.74M
{
96
1.74M
  txSlot* function = frame + 2;
97
1.74M
  txSlot* _this = frame + 3;
98
1.74M
  if (function->kind == XS_REFERENCE_KIND) {
99
1.74M
    function = function->value.reference;
100
1.74M
    if (mxIsFunction(function)) {
101
1.68M
      if (!(frame->flag & XS_TARGET_FLAG)) {
102
1.64M
        txSlot* home = mxFunctionInstanceHome(function)->value.home.object;
103
1.64M
        if (home) {
104
456k
          if (mxIsFunction(home)) {
105
85.1k
            fxBufferFunctionName(the, buffer, size, home, ".");
106
85.1k
          }
107
370k
          else {
108
370k
            txSlot* constructor = mxBehaviorGetProperty(the, home, mxID(_constructor), 0, XS_OWN);
109
370k
            if (constructor) {
110
223k
              if (constructor->kind == XS_REFERENCE_KIND) {
111
223k
                constructor = constructor->value.reference;
112
223k
                if (mxIsFunction(constructor))
113
223k
                  fxBufferFunctionName(the, buffer, size, constructor, ".prototype.");
114
223k
              }
115
223k
            }
116
147k
            else if (_this->kind == XS_REFERENCE_KIND) {
117
145k
              fxBufferObjectName(the, buffer, size, _this->value.reference, ".");
118
145k
            }
119
370k
          }
120
456k
        }
121
1.64M
      }
122
1.68M
      fxBufferFunctionName(the, buffer, size, function, "");
123
1.68M
    }
124
1.74M
  }
125
#if mxHostFunctionPrimitive
126
  else if (function->kind == XS_HOST_FUNCTION_KIND) {
127
    fxBufferFunctionNameAddress(the, buffer, size, function->value.hostFunction.builder->id, function->value.hostFunction.builder->callback, function->value.hostFunction.profileID);
128
  }
129
#endif
130
1.20k
  else
131
1.20k
    c_strncat(buffer, "(host)", size - mxStringLength(buffer) - 1);
132
1.74M
  c_strncat(buffer, suffix, size - mxStringLength(buffer) - 1);
133
1.74M
}
134
135
void fxBufferFunctionName(txMachine* the, txString buffer, txSize size, txSlot* function, txString suffix)
136
1.99M
{
137
1.99M
  txSlot* slot = mxFunctionInstanceCode(function);
138
1.99M
  txSlot* home = mxFunctionInstanceHome(function);
139
1.99M
  if ((slot->kind == XS_CODE_KIND) || (slot->kind == XS_CODE_X_KIND))
140
1.06M
    fxBufferFunctionNameAddress(the, buffer, size, slot->ID, C_NULL, home->ID);
141
922k
  else
142
922k
    fxBufferFunctionNameAddress(the, buffer, size, slot->ID, slot->value.callback.address, home->ID);
143
1.99M
    c_strncat(buffer, suffix, size - mxStringLength(buffer) - 1);
144
1.99M
}
145
146
void fxBufferFunctionNameAddress(txMachine* the, txString buffer, txSize size, txID id, txCallback address, txID profileID)
147
1.99M
{
148
1.99M
  txInteger length;
149
1.99M
  if (id != XS_NO_ID) {
150
1.04M
    txBoolean adorn;
151
1.04M
    txString string = fxGetKeyString(the, id, &adorn);
152
1.04M
    if (adorn)
153
159
      c_strncat(buffer, "[", size - mxStringLength(buffer) - 1);
154
1.04M
    fxBufferName(buffer, string, size - mxStringLength(buffer) - 1);
155
1.04M
    if (adorn)
156
159
      c_strncat(buffer, "]", size - mxStringLength(buffer) - 1);
157
1.04M
    return;
158
1.04M
  }
159
951k
  if (address) {
160
33.0k
    c_strncat(buffer, "@", size - mxStringLength(buffer) - 1);
161
33.0k
#if mxMacOSX || mxLinux
162
33.0k
    Dl_info info;
163
33.0k
    if (dladdr(address, &info) && info.dli_sname)
164
32.7k
      c_strncat(buffer, info.dli_sname, size - mxStringLength(buffer) - 1);
165
244
    else 
166
244
#endif
167
244
    {
168
244
      c_strncat(buffer, "anonymous-", size - mxStringLength(buffer) - 1);
169
244
      length = mxStringLength(buffer);
170
244
      fxIntegerToString(the, profileID, buffer + length, size - length - 1);
171
244
    }
172
33.0k
  }
173
918k
  else {
174
918k
    c_strncat(buffer, "(anonymous-", size - mxStringLength(buffer) - 1);
175
918k
    length = mxStringLength(buffer);
176
918k
    fxIntegerToString(the, profileID, buffer + length, size - length - 1);
177
918k
    c_strncat(buffer, ")", size - mxStringLength(buffer) - 1);
178
918k
  }
179
951k
}
180
181
void fxBufferObjectName(txMachine* the, txString buffer, txSize size, txSlot* object, txString suffix)
182
145k
{
183
145k
  txSlot* slot = mxBehaviorGetProperty(the, object, mxID(_Symbol_toStringTag), 0, XS_ANY);
184
145k
  if (slot && ((slot->kind == XS_STRING_KIND) || (slot->kind == XS_STRING_X_KIND)) && !c_isEmpty(slot->value.string)) {
185
72.5k
    fxBufferName(buffer, slot->value.string, size - mxStringLength(buffer) - 1);
186
72.5k
    c_strncat(buffer, suffix, size - mxStringLength(buffer) - 1);
187
72.5k
  }
188
145k
}
189
190
void fxBufferName(txString dst, txString src, txSize size)
191
1.11M
{
192
1.11M
  dst += mxStringLength(dst);
193
8.75M
  for (;;) {
194
8.75M
    txInteger c;
195
8.75M
    txSize length;
196
8.75M
    src = mxStringByteDecode(src, &c);
197
8.75M
    if (c == C_EOF)
198
1.11M
      break;
199
7.64M
    length = mxStringByteLength(c);
200
7.64M
    if (length > size)
201
1.88k
      break;
202
7.64M
    dst = mxStringByteEncode(dst, c);
203
7.64M
    size -= length;
204
7.64M
  }
205
1.11M
  *dst = 0;
206
1.11M
}
207
208
txString fxConcatString(txMachine* the, txSlot* a, txSlot* b)
209
9.96M
{
210
9.96M
  txSize aSize = mxStringLength(a->value.string);
211
9.96M
  txSize bSize = mxStringLength(b->value.string);
212
9.96M
  txSize resultSize = fxAddChunkSizes(the, fxAddChunkSizes(the, aSize, bSize), 1);
213
9.96M
  txString result = (txString)fxNewChunk(the, resultSize);
214
9.96M
  c_memcpy(result, a->value.string, aSize);
215
9.96M
  c_memcpy(result + aSize, b->value.string, bSize + 1);
216
9.96M
  a->value.string = result;
217
9.96M
  a->kind = XS_STRING_KIND;
218
9.96M
  return result;
219
9.96M
}
220
221
txString fxConcatStringC(txMachine* the, txSlot* a, txString b)
222
1.77M
{
223
1.77M
  txSize aSize = mxStringLength(a->value.string);
224
1.77M
  txSize bSize = mxStringLength(b);
225
1.77M
  txSize resultSize = fxAddChunkSizes(the, fxAddChunkSizes(the, aSize, bSize), 1);
226
1.77M
  txString result = C_NULL;
227
1.77M
  if (a->kind == XS_STRING_KIND)
228
1.77M
    result = (txString)fxRenewChunk(the, a->value.string, resultSize);
229
1.77M
  if (!result) {
230
63
    result = (txString)fxNewChunk(the, resultSize);
231
63
    c_memcpy(result, a->value.string, aSize);
232
63
    a->value.string = result;
233
63
    a->kind = XS_STRING_KIND;
234
63
  }
235
1.77M
  c_memcpy(result + aSize, b, bSize + 1);
236
1.77M
  return result;
237
1.77M
}
238
239
txString fxCopyString(txMachine* the, txSlot* a, txSlot* b)
240
0
{
241
0
  txString result = b->value.string;
242
0
  a->value.string = result;
243
0
  a->kind = b->kind;
244
0
  return result;
245
0
}
246
247
txString fxCopyStringC(txMachine* the, txSlot* a, txString b)
248
39.1M
{
249
39.1M
  txSize bSize = mxStringLength(b);
250
39.1M
  txSize resultSize = fxAddChunkSizes(the, bSize, 1);
251
39.1M
  txString result = (txString)fxNewChunk(the, resultSize);
252
39.1M
  c_memcpy(result, b, resultSize);
253
39.1M
  a->value.string = result;
254
39.1M
  a->kind = XS_STRING_KIND;
255
39.1M
  return result;
256
39.1M
}
257
258
txBoolean fxIsCanonicalIndex(txMachine* the, txID id)
259
329k
{
260
329k
  txSlot* key = fxGetKey(the, id);
261
329k
  if (key->flag & XS_DONT_ENUM_FLAG) {
262
317k
    txString string = key->value.key.string;
263
317k
    char buffer[256], c;
264
317k
    txNumber number;
265
317k
    c = c_read8(string);
266
317k
    if (('+' != c) && ('-' != c) && ('.' != c) && ('I' != c) && ('N' != c) && !(('0' <= c) && ('9' >= c)))
267
306k
      return 0;
268
11.2k
    number = fxStringToNumber(the, string, 1);
269
11.2k
    if (number == -0)
270
2.61k
      return 1;
271
8.59k
    fxNumberToString(the, number, buffer, sizeof(buffer), 0, 0);
272
8.59k
    if (!c_strcmp(string, buffer)) {
273
2.00k
      return 1;
274
2.00k
    }
275
8.59k
  }
276
18.9k
  return 0;
277
329k
}
278
279
int fxStringGetter(void* theStream)
280
90.6M
{
281
90.6M
  txStringStream* aStream = (txStringStream*)theStream;
282
90.6M
  int result = C_EOF;
283
  
284
90.6M
  if (aStream->offset < aStream->size) {
285
90.4M
    result = *(aStream->slot->value.string + aStream->offset);
286
90.4M
    aStream->offset++;
287
90.4M
  }
288
90.6M
  return result;
289
90.6M
}
290
291
int fxStringCGetter(void* theStream)
292
38.3M
{
293
38.3M
  txStringCStream* aStream = (txStringCStream*)theStream;
294
38.3M
  int result = C_EOF;
295
  
296
38.3M
  if (aStream->offset < aStream->size) {
297
38.3M
    result = *(aStream->buffer + aStream->offset);
298
38.3M
    aStream->offset++;
299
38.3M
  }
300
38.3M
  return result;
301
38.3M
}
302
303
void fxJump(txMachine* the)
304
2.71M
{
305
2.71M
  txJump* aJump = the->firstJump;
306
2.71M
  c_longjmp(aJump->buffer, 1);
307
2.71M
}