Coverage Report

Created: 2025-02-03 07:01

/src/moddable/xs/sources/xsSourceMap.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2016-2022  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
#include "xsScript.h"
39
40
static void fxSourceMapLines(txParser* parser, txString mappings);
41
static txInteger fxSourceMapValue(txParser* parser, txString* p);
42
43
0
#define mxAssert(ASSERTION,MESSAGE) if (!(ASSERTION)) { fxReportParserError(parser, parser->states[0].line, MESSAGE); return; }
44
45
void fxParserSourceMap(txParser* parser, void* theStream, txGetter theGetter, txUnsigned flags, txString* name)
46
0
{
47
0
  txInteger line = parser->states[0].line;
48
0
  txNode* root = parser->root;
49
0
  txNode* object;
50
0
    txNode* item;
51
0
    txNode* node;
52
0
  txPropertyAtNode* property;
53
0
  txString id;
54
0
  txInteger version = 0;
55
0
  txString source = NULL;
56
0
  txString mappings = NULL;
57
  
58
0
  parser->states[0].line = 0;
59
0
  parser->root = NULL;
60
0
  parser->stream = theStream;
61
0
  parser->getter = theGetter;
62
  
63
0
  parser->states[2].line = 1;
64
0
  parser->states[2].crlf = 0;
65
0
  parser->states[2].escaped = 0;
66
0
  parser->states[2].integer = 0;
67
0
  parser->states[2].modifierLength = 0;
68
0
  parser->states[2].modifier = parser->emptyString;
69
0
  parser->states[2].number = 0;
70
0
  parser->states[2].stringLength = 0;
71
0
  parser->states[2].string = parser->emptyString;
72
0
  parser->states[2].symbol = C_NULL;
73
0
  parser->states[2].token = XS_NO_TOKEN;
74
  
75
0
  parser->lookahead = 0;
76
0
#if mxCESU8
77
0
  parser->surrogate = 0;
78
0
#endif
79
0
  fxGetNextCharacter(parser);
80
0
  fxGetNextCharacter(parser);
81
0
  fxGetNextTokenJSON(parser);
82
0
  fxGetNextTokenJSON(parser);
83
0
  fxJSONValue(parser);
84
0
  if (parser->errorCount)
85
0
    return;
86
0
  object = parser->root;
87
0
  parser->states[0].line = line;
88
0
  parser->root = root;
89
  
90
0
  mxAssert(object->description->token == XS_TOKEN_OBJECT, "source map: no object");
91
0
  mxAssert(((txObjectNode*)object)->items, "source map: no properties");
92
0
  item = ((txObjectNode*)object)->items->first;
93
0
  while (item) {
94
0
    mxAssert(item->description->token == XS_TOKEN_PROPERTY_AT, "source map: no property");
95
0
    property = (txPropertyAtNode*)item;
96
0
    mxAssert(property->at->description->token == XS_TOKEN_STRING, "source map: no property name");
97
0
    id = ((txStringNode*)(property->at))->value;
98
0
    if (!c_strcmp(id, "version")) {
99
0
      mxAssert(property->value->description->token == XS_TOKEN_INTEGER, "source map: version is no integer");
100
0
      version = ((txIntegerNode*)(property->value))->value;
101
0
    }
102
0
    else if (!c_strcmp(id, "sources")) {
103
0
      mxAssert(property->value->description->token == XS_TOKEN_ARRAY, "source map: sources is no array");
104
0
      node = ((txArrayNode*)(property->value))->items->first;
105
0
      mxAssert(node->description->token == XS_TOKEN_STRING, "source map: sources[0] is no string");
106
0
      source = ((txStringNode*)(node))->value;
107
0
    }
108
0
    else if (!c_strcmp(id, "mappings")) {
109
0
      mxAssert(property->value->description->token == XS_TOKEN_STRING, "source map: mappings is no string");
110
0
      mappings = ((txStringNode*)(property->value))->value;
111
0
    }
112
0
    item = item->next;
113
0
  }
114
0
  mxAssert(version == 3, "source map: version is not 3");
115
0
  mxAssert(source, "source map: no source");
116
0
  mxAssert(mappings, "source map: no mappings");
117
  
118
0
  parser->lines = fxNewParserChunkClear(parser, (1 + line) * sizeof(txInteger));
119
120
0
  fxSourceMapLines(parser, mappings);
121
0
  *name = source;
122
0
}
123
124
void fxSourceMapLines(txParser* parser, txString mappings)
125
0
{
126
0
  enum { BEGIN, SOURCE, LINE, COLUMN, NAME, END };
127
0
  txInteger generatedLine = 0;
128
//  txInteger generatedColumn = 0;
129
//  txInteger name = 0;
130
//  txInteger source = 0;
131
0
  txInteger sourceLine = 0;
132
//  txInteger sourceColumn = 0;
133
0
  txInteger state = BEGIN;
134
0
  txString p = mappings;
135
0
  char c;
136
0
  while ((c = *p)) {
137
0
    if (c == ';') {
138
0
      p++;
139
0
      if ((state >= NAME) && (generatedLine < parser->states[0].line))
140
0
        parser->lines[1 + generatedLine] = 1 + sourceLine;
141
0
      generatedLine++;
142
//      generatedColumn = 0;
143
0
      state = BEGIN;
144
0
    }
145
0
    else if (c == ',') {
146
0
      p++;
147
0
      if ((state >= NAME) && (generatedLine < parser->states[0].line))
148
0
        parser->lines[1 + generatedLine] = 1 + sourceLine;
149
0
      state = BEGIN;
150
0
    }
151
0
    else {
152
0
      txInteger value = fxSourceMapValue(parser, &p);
153
0
      switch(state) {
154
0
      case BEGIN:
155
//        generatedColumn += value;
156
0
        state = SOURCE;
157
0
        break;
158
0
      case SOURCE:
159
//        source += value;
160
0
        state = LINE;
161
0
        break;
162
0
      case LINE:
163
0
        sourceLine += value;
164
0
        state = COLUMN;
165
0
        break;
166
0
      case COLUMN:
167
//        sourceColumn += value;
168
0
        state = NAME;
169
0
        break;
170
0
      case NAME:
171
//        name += value;
172
0
        state = END;
173
0
        break;
174
0
      }
175
0
    }
176
0
  }
177
0
}
178
179
0
#define VLQ_SHIFT 5
180
// binary: 100000
181
0
#define VLQ_CONTINUATION_BIT (1 << VLQ_SHIFT)
182
// binary: 011111
183
0
#define VLQ_MASK_BITS (VLQ_CONTINUATION_BIT - 1)
184
185
txInteger fxSourceMapValue(txParser* parser, txString* p)
186
0
{
187
0
  txInteger continuation, digit, result = 0, shift = 0;
188
0
  txString q = *p;
189
0
  do {
190
0
    char c = *q++;
191
0
    if (('A' <= c) && (c <= 'Z'))
192
0
      digit = c - 'A';
193
0
    else if (('a' <= c) && (c <= 'z'))
194
0
      digit = c - 'a' + 26;
195
0
    else if (('0' <= c) && (c <= '9'))
196
0
      digit = c - '0' + 52;
197
0
    else if (c == '+')
198
0
      digit = 62;
199
0
    else if (c == '/')
200
0
      digit = 63;
201
0
    else
202
0
      fxReportParserError(parser, parser->states[0].line, "source map: unexpected character"); 
203
0
    continuation = digit & VLQ_CONTINUATION_BIT;
204
0
    digit &= VLQ_MASK_BITS;
205
0
    result += (digit << shift);
206
0
    shift += VLQ_SHIFT;
207
0
  } while (continuation);
208
0
  *p = q;
209
0
  shift = result >> 1;
210
0
  return ((result & 1) == 1) ? -shift : shift;
211
0
}
212
213
214
215
216
217
218