Changeset 44968 in webkit
- Timestamp:
- Jun 22, 2009 6:27:54 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r44931 r44968 1 2009-06-22 Oliver Hunt <oliver@apple.com> 2 3 Reviewed by Darin Adler. 4 5 Bug 26591: Support revivers in JSON.parse 6 <https://bugs.webkit.org/show_bug.cgi?id=26591> 7 8 Add reviver support to JSON.parse. This completes the JSON object. 9 10 * runtime/JSONObject.cpp: 11 (JSC::Walker::Walker): 12 (JSC::Walker::callReviver): 13 (JSC::Walker::walk): 14 (JSC::JSONProtoFuncParse): 15 1 16 2009-06-21 Oliver Hunt <oliver@apple.com> 2 17 -
trunk/JavaScriptCore/runtime/JSONObject.cpp
r44923 r44968 588 588 } 589 589 590 // ECMA-262 v5 15.12.3 590 class Walker { 591 public: 592 Walker(ExecState* exec, JSObject* function, CallType callType, CallData callData) 593 : m_exec(exec) 594 , m_function(function) 595 , m_callType(callType) 596 , m_callData(callData) 597 { 598 } 599 JSValue walk(JSValue unfiltered); 600 private: 601 JSValue callReviver(JSValue property, JSValue unfiltered) 602 { 603 JSValue args[] = { property, unfiltered }; 604 ArgList argList(args, 2); 605 return call(m_exec, m_function, m_callType, m_callData, jsNull(), argList); 606 } 607 608 friend class Holder; 609 610 ExecState* m_exec; 611 JSObject* m_function; 612 CallType m_callType; 613 CallData m_callData; 614 }; 615 616 enum WalkerState { StateUnknown, ArrayStartState, ArrayStartVisitMember, ArrayEndVisitMember, 617 ObjectStartState, ObjectStartVisitMember, ObjectEndVisitMember }; 618 NEVER_INLINE JSValue Walker::walk(JSValue unfiltered) 619 { 620 Vector<PropertyNameArray, 16> propertyStack; 621 Vector<uint32_t, 16> indexStack; 622 Vector<JSObject*, 16> objectStack; 623 Vector<JSArray*, 16> arrayStack; 624 625 Vector<WalkerState, 16> stateStack; 626 WalkerState state = StateUnknown; 627 JSValue inValue = unfiltered; 628 JSValue outValue = jsNull(); 629 while (1) { 630 switch (state) { 631 arrayStartState: 632 case ArrayStartState: { 633 ASSERT(inValue.isObject()); 634 ASSERT(isJSArray(&m_exec->globalData(), asObject(inValue))); 635 JSArray* array = asArray(inValue); 636 arrayStack.append(array); 637 indexStack.append(0); 638 // fallthrough 639 } 640 arrayStartVisitMember: 641 case ArrayStartVisitMember: { 642 JSArray* array = arrayStack.last(); 643 uint32_t index = indexStack.last(); 644 if (index == array->length()) { 645 outValue = array; 646 arrayStack.removeLast(); 647 indexStack.removeLast(); 648 break; 649 } 650 inValue = array->getIndex(index); 651 if (inValue.isObject()) { 652 stateStack.append(ArrayEndVisitMember); 653 goto stateUnknown; 654 } else 655 outValue = inValue; 656 // fallthrough 657 } 658 case ArrayEndVisitMember: { 659 JSArray* array = arrayStack.last(); 660 array->setIndex(indexStack.last(), callReviver(jsString(m_exec, UString::from(indexStack.last())), outValue)); 661 if (m_exec->hadException()) 662 return jsNull(); 663 indexStack.last()++; 664 goto arrayStartVisitMember; 665 } 666 objectStartState: 667 case ObjectStartState: { 668 ASSERT(inValue.isObject()); 669 ASSERT(!isJSArray(&m_exec->globalData(), asObject(inValue))); 670 JSObject* object = asObject(inValue); 671 objectStack.append(object); 672 indexStack.append(0); 673 propertyStack.append(PropertyNameArray(m_exec)); 674 object->getPropertyNames(m_exec, propertyStack.last()); 675 // fallthrough 676 } 677 objectStartVisitMember: 678 case ObjectStartVisitMember: { 679 JSObject* object = objectStack.last(); 680 uint32_t index = indexStack.last(); 681 PropertyNameArray& properties = propertyStack.last(); 682 if (index == properties.size()) { 683 outValue = object; 684 objectStack.removeLast(); 685 indexStack.removeLast(); 686 propertyStack.removeLast(); 687 break; 688 } 689 PropertySlot slot; 690 object->getOwnPropertySlot(m_exec, properties[index], slot); 691 inValue = slot.getValue(m_exec, properties[index]); 692 ASSERT(!m_exec->hadException()); 693 if (inValue.isObject()) { 694 stateStack.append(ObjectEndVisitMember); 695 goto stateUnknown; 696 } else 697 outValue = inValue; 698 // fallthrough 699 } 700 case ObjectEndVisitMember: { 701 JSObject* object = objectStack.last(); 702 Identifier prop = propertyStack.last()[indexStack.last()]; 703 PutPropertySlot slot; 704 object->put(m_exec, prop, callReviver(jsString(m_exec, prop.ustring()), outValue), slot); 705 if (m_exec->hadException()) 706 return jsNull(); 707 indexStack.last()++; 708 goto objectStartVisitMember; 709 } 710 stateUnknown: 711 case StateUnknown: 712 if (!inValue.isObject()) { 713 outValue = inValue; 714 break; 715 } 716 if (isJSArray(&m_exec->globalData(), asObject(inValue))) 717 goto arrayStartState; 718 goto objectStartState; 719 } 720 if (stateStack.isEmpty()) 721 break; 722 state = stateStack.last(); 723 stateStack.removeLast(); 724 } 725 return callReviver(jsEmptyString(m_exec), outValue); 726 } 727 728 // ECMA-262 v5 15.12.2 591 729 JSValue JSC_HOST_CALL JSONProtoFuncParse(ExecState* exec, JSObject*, JSValue, const ArgList& args) 592 730 { … … 599 737 600 738 LiteralParser jsonParser(exec, source, LiteralParser::StrictJSON); 601 JSValue parsedObject= jsonParser.tryLiteralParse();602 if (! parsedObject)739 JSValue unfiltered = jsonParser.tryLiteralParse(); 740 if (!unfiltered) 603 741 return throwError(exec, SyntaxError, "Unable to parse JSON string"); 604 742 605 return parsedObject; 743 if (args.size() < 2) 744 return unfiltered; 745 746 JSValue function = args.at(1); 747 CallData callData; 748 CallType callType = function.getCallData(callData); 749 if (callType == CallTypeNone) 750 return unfiltered; 751 return Walker(exec, asObject(function), callType, callData).walk(unfiltered); 606 752 } 607 753 -
trunk/LayoutTests/ChangeLog
r44961 r44968 1 2009-06-22 Oliver Hunt <oliver@apple.com> 2 3 Reviewed by Darin Adler. 4 5 Bug 26591: Support revivers in JSON.parse 6 <https://bugs.webkit.org/show_bug.cgi?id=26591> 7 8 Test cases for JSON.parse with a reviver function. 9 10 * fast/js/JSON-parse-expected.txt: 11 * fast/js/resources/JSON-parse.js: 12 (createTests.log): 13 (createTests.result): 14 (createTests.logOrder): 15 (createTests.var): 16 (createTests.throwAfterFifthCall): 17 (createTests): 18 1 19 2009-06-22 Simon Fraser <simon.fraser@apple.com> 2 20 -
trunk/LayoutTests/fast/js/JSON-parse-expected.txt
r44923 r44968 386 386 return jsonObject.parse(JSON.stringify(complexObject,null,"\n")); 387 387 } 388 PASS JSON.stringify(tests[i](nativeJSON)) is JSON.stringify(tests[i](JSON)) 389 function (jsonObject) { 390 return jsonObject.parse(JSON.stringify(complexObject,null,"\n")); 391 } 392 PASS JSON.stringify(tests[i](nativeJSON)) is tests[i].expected 388 PASS JSON.stringify(tests[i](nativeJSON)) is tests[i].expected 389 function (jsonObject) { 390 return jsonObject.parse("true", log); 391 } 392 PASS JSON.stringify(tests[i](nativeJSON)) is JSON.stringify(tests[i](JSON)) 393 function (jsonObject) { 394 return jsonObject.parse("false", log); 395 } 396 PASS JSON.stringify(tests[i](nativeJSON)) is JSON.stringify(tests[i](JSON)) 397 function (jsonObject) { 398 return jsonObject.parse("null", log); 399 } 400 PASS JSON.stringify(tests[i](nativeJSON)) is JSON.stringify(tests[i](JSON)) 401 function (jsonObject) { 402 return jsonObject.parse("1", log); 403 } 404 PASS JSON.stringify(tests[i](nativeJSON)) is JSON.stringify(tests[i](JSON)) 405 function (jsonObject) { 406 return jsonObject.parse("1.5", log); 407 } 408 PASS JSON.stringify(tests[i](nativeJSON)) is JSON.stringify(tests[i](JSON)) 409 function (jsonObject) { 410 return jsonObject.parse('"a string"', log); 411 } 412 PASS JSON.stringify(tests[i](nativeJSON)) is JSON.stringify(tests[i](JSON)) 413 function (jsonObject) { 414 return jsonObject.parse(JSON.stringify(simpleArray), log); 415 } 416 PASS JSON.stringify(tests[i](nativeJSON)) is JSON.stringify(tests[i](JSON)) 417 function (jsonObject) { 418 return jsonObject.parse(JSON.stringify(complexArray), log); 419 } 420 PASS JSON.stringify(tests[i](nativeJSON)) is JSON.stringify(tests[i](JSON)) 421 function (jsonObject) { 422 return jsonObject.parse(JSON.stringify(simpleObject), log); 423 } 424 PASS JSON.stringify(tests[i](nativeJSON)) is JSON.stringify(tests[i](JSON)) 425 function (jsonObject) { 426 return jsonObject.parse(JSON.stringify(complexObject), log); 427 } 428 PASS JSON.stringify(tests[i](nativeJSON)) is JSON.stringify(tests[i](JSON)) 429 function (jsonObject) { 430 logOrderString = ""; 431 return jsonObject.parse("true", logOrder); 432 } 433 PASS JSON.stringify(tests[i](nativeJSON)) is JSON.stringify(tests[i](JSON)) 434 function (jsonObject) { 435 logOrderString = ""; 436 return jsonObject.parse("false", logOrder); 437 } 438 PASS JSON.stringify(tests[i](nativeJSON)) is JSON.stringify(tests[i](JSON)) 439 function (jsonObject) { 440 logOrderString = ""; 441 return jsonObject.parse("null", logOrder); 442 } 443 PASS JSON.stringify(tests[i](nativeJSON)) is JSON.stringify(tests[i](JSON)) 444 function (jsonObject) { 445 logOrderString = ""; 446 return jsonObject.parse("1", logOrder); 447 } 448 PASS JSON.stringify(tests[i](nativeJSON)) is JSON.stringify(tests[i](JSON)) 449 function (jsonObject) { 450 logOrderString = ""; 451 return jsonObject.parse("1.5", logOrder); 452 } 453 PASS JSON.stringify(tests[i](nativeJSON)) is JSON.stringify(tests[i](JSON)) 454 function (jsonObject) { 455 logOrderString = ""; 456 return jsonObject.parse('"a string"', logOrder); 457 } 458 PASS JSON.stringify(tests[i](nativeJSON)) is JSON.stringify(tests[i](JSON)) 459 function (jsonObject) { 460 logOrderString = ""; 461 return jsonObject.parse(JSON.stringify(simpleArray), logOrder); 462 } 463 PASS JSON.stringify(tests[i](nativeJSON)) is JSON.stringify(tests[i](JSON)) 464 function (jsonObject) { 465 logOrderString = ""; 466 return jsonObject.parse(JSON.stringify(complexArray), logOrder); 467 } 468 PASS JSON.stringify(tests[i](nativeJSON)) is JSON.stringify(tests[i](JSON)) 469 function (jsonObject) { 470 logOrderString = ""; 471 return jsonObject.parse(JSON.stringify(simpleObject), logOrder); 472 } 473 PASS JSON.stringify(tests[i](nativeJSON)) is JSON.stringify(tests[i](JSON)) 474 function (jsonObject) { 475 logOrderString = ""; 476 return jsonObject.parse(JSON.stringify(complexObject), logOrder); 477 } 478 PASS JSON.stringify(tests[i](nativeJSON)) is JSON.stringify(tests[i](JSON)) 479 function (jsonObject) { 480 logOrderString = ""; 481 jsonObject.parse("true", logOrder); 482 return logOrderString; 483 } 484 PASS JSON.stringify(tests[i](nativeJSON)) is JSON.stringify(tests[i](JSON)) 485 function (jsonObject) { 486 logOrderString = ""; 487 jsonObject.parse("false", logOrder); 488 return logOrderString; 489 } 490 PASS JSON.stringify(tests[i](nativeJSON)) is JSON.stringify(tests[i](JSON)) 491 function (jsonObject) { 492 logOrderString = ""; 493 jsonObject.parse("null", logOrder); 494 return logOrderString; 495 } 496 PASS JSON.stringify(tests[i](nativeJSON)) is JSON.stringify(tests[i](JSON)) 497 function (jsonObject) { 498 logOrderString = ""; 499 jsonObject.parse("1", logOrder); 500 return logOrderString; 501 } 502 PASS JSON.stringify(tests[i](nativeJSON)) is JSON.stringify(tests[i](JSON)) 503 function (jsonObject) { 504 logOrderString = ""; 505 jsonObject.parse("1.5", logOrder); 506 return logOrderString; 507 } 508 PASS JSON.stringify(tests[i](nativeJSON)) is JSON.stringify(tests[i](JSON)) 509 function (jsonObject) { 510 logOrderString = ""; 511 jsonObject.parse('"a string"', logOrder); 512 return logOrderString; 513 } 514 PASS JSON.stringify(tests[i](nativeJSON)) is JSON.stringify(tests[i](JSON)) 515 function (jsonObject) { 516 logOrderString = ""; 517 jsonObject.parse(JSON.stringify(simpleArray), logOrder); 518 return logOrderString; 519 } 520 PASS JSON.stringify(tests[i](nativeJSON)) is JSON.stringify(tests[i](JSON)) 521 function (jsonObject) { 522 logOrderString = ""; 523 jsonObject.parse(JSON.stringify(complexArray), logOrder); 524 return logOrderString; 525 } 526 PASS JSON.stringify(tests[i](nativeJSON)) is JSON.stringify(tests[i](JSON)) 527 function (jsonObject) { 528 logOrderString = ""; 529 jsonObject.parse(JSON.stringify(simpleObject), logOrder); 530 return logOrderString; 531 } 532 PASS JSON.stringify(tests[i](nativeJSON)) is JSON.stringify(tests[i](JSON)) 533 function (jsonObject) { 534 logOrderString = ""; 535 jsonObject.parse(JSON.stringify(complexObject), logOrder); 536 return logOrderString; 537 } 538 PASS JSON.stringify(tests[i](nativeJSON)) is JSON.stringify(tests[i](JSON)) 539 function (jsonObject) { 540 callCount = 0; 541 logOrderString = ""; 542 return jsonObject.parse(JSON.stringify(complexArray), throwAfterFifthCall); 543 } 544 PASS tests[i](nativeJSON) threw exception from reviver. 545 function (jsonObject) { 546 callCount = 0; 547 logOrderString = ""; 548 return jsonObject.parse(JSON.stringify(simpleObject), throwAfterFifthCall); 549 } 550 PASS JSON.stringify(tests[i](nativeJSON)) is JSON.stringify(tests[i](JSON)) 551 function (jsonObject) { 552 callCount = 0; 553 logOrderString = ""; 554 return jsonObject.parse(JSON.stringify(complexObject), throwAfterFifthCall); 555 } 556 PASS tests[i](nativeJSON) threw exception from reviver. 557 function (jsonObject) { 558 callCount = 0; 559 logOrderString = ""; 560 try { jsonObject.parse(JSON.stringify(complexArray), throwAfterFifthCall); } catch (e) {} 561 return logOrderString; 562 } 563 PASS JSON.stringify(tests[i](nativeJSON)) is JSON.stringify(tests[i](JSON)) 564 function (jsonObject) { 565 callCount = 0; 566 logOrderString = ""; 567 try { jsonObject.parse(JSON.stringify(simpleObject), throwAfterFifthCall); } catch (e) {} 568 return logOrderString; 569 } 570 PASS JSON.stringify(tests[i](nativeJSON)) is JSON.stringify(tests[i](JSON)) 571 function (jsonObject) { 572 callCount = 0; 573 logOrderString = ""; 574 try { jsonObject.parse(JSON.stringify(complexObject), throwAfterFifthCall); } catch (e) {} 575 return logOrderString; 576 } 577 PASS JSON.stringify(tests[i](nativeJSON)) is JSON.stringify(tests[i](JSON)) 393 578 PASS successfullyParsed is true 394 579 -
trunk/LayoutTests/fast/js/resources/JSON-parse.js
r44923 r44968 351 351 return jsonObject.parse(JSON.stringify(complexObject,null,"\n")); 352 352 }); 353 result.push(function(jsonObject){354 return jsonObject.parse(JSON.stringify(complexObject,null,"\n"));355 });356 353 result[result.length - 1].expected = JSON.stringify(complexObject); 357 354 function log(key, value) { 355 var o = {}; 356 o[key] = value; 357 o.keyType = typeof key; 358 return o; 359 } 360 result.push(function(jsonObject){ 361 return jsonObject.parse("true", log); 362 }); 363 result.push(function(jsonObject){ 364 return jsonObject.parse("false", log); 365 }); 366 result.push(function(jsonObject){ 367 return jsonObject.parse("null", log); 368 }); 369 result.push(function(jsonObject){ 370 return jsonObject.parse("1", log); 371 }); 372 result.push(function(jsonObject){ 373 return jsonObject.parse("1.5", log); 374 }); 375 result.push(function(jsonObject){ 376 return jsonObject.parse('"a string"', log); 377 }); 378 result.push(function(jsonObject){ 379 return jsonObject.parse(JSON.stringify(simpleArray), log); 380 }); 381 result.push(function(jsonObject){ 382 return jsonObject.parse(JSON.stringify(complexArray), log); 383 }); 384 result.push(function(jsonObject){ 385 return jsonObject.parse(JSON.stringify(simpleObject), log); 386 }); 387 result.push(function(jsonObject){ 388 return jsonObject.parse(JSON.stringify(complexObject), log); 389 }); 390 var logOrderString; 391 function logOrder(key, value) { 392 logOrderString += key +":"+JSON.stringify(value); 393 return null; 394 } 395 result.push(function(jsonObject){ 396 logOrderString = ""; 397 return jsonObject.parse("true", logOrder); 398 }); 399 result.push(function(jsonObject){ 400 logOrderString = ""; 401 return jsonObject.parse("false", logOrder); 402 }); 403 result.push(function(jsonObject){ 404 logOrderString = ""; 405 return jsonObject.parse("null", logOrder); 406 }); 407 result.push(function(jsonObject){ 408 logOrderString = ""; 409 return jsonObject.parse("1", logOrder); 410 }); 411 result.push(function(jsonObject){ 412 logOrderString = ""; 413 return jsonObject.parse("1.5", logOrder); 414 }); 415 result.push(function(jsonObject){ 416 logOrderString = ""; 417 return jsonObject.parse('"a string"', logOrder); 418 }); 419 result.push(function(jsonObject){ 420 logOrderString = ""; 421 return jsonObject.parse(JSON.stringify(simpleArray), logOrder); 422 }); 423 result.push(function(jsonObject){ 424 logOrderString = ""; 425 return jsonObject.parse(JSON.stringify(complexArray), logOrder); 426 }); 427 result.push(function(jsonObject){ 428 logOrderString = ""; 429 return jsonObject.parse(JSON.stringify(simpleObject), logOrder); 430 }); 431 result.push(function(jsonObject){ 432 logOrderString = ""; 433 return jsonObject.parse(JSON.stringify(complexObject), logOrder); 434 }); 435 result.push(function(jsonObject){ 436 logOrderString = ""; 437 jsonObject.parse("true", logOrder); 438 return logOrderString; 439 }); 440 result.push(function(jsonObject){ 441 logOrderString = ""; 442 jsonObject.parse("false", logOrder); 443 return logOrderString; 444 }); 445 result.push(function(jsonObject){ 446 logOrderString = ""; 447 jsonObject.parse("null", logOrder); 448 return logOrderString; 449 }); 450 result.push(function(jsonObject){ 451 logOrderString = ""; 452 jsonObject.parse("1", logOrder); 453 return logOrderString; 454 }); 455 result.push(function(jsonObject){ 456 logOrderString = ""; 457 jsonObject.parse("1.5", logOrder); 458 return logOrderString; 459 }); 460 result.push(function(jsonObject){ 461 logOrderString = ""; 462 jsonObject.parse('"a string"', logOrder); 463 return logOrderString; 464 }); 465 result.push(function(jsonObject){ 466 logOrderString = ""; 467 jsonObject.parse(JSON.stringify(simpleArray), logOrder); 468 return logOrderString; 469 }); 470 result.push(function(jsonObject){ 471 logOrderString = ""; 472 jsonObject.parse(JSON.stringify(complexArray), logOrder); 473 return logOrderString; 474 }); 475 result.push(function(jsonObject){ 476 logOrderString = ""; 477 jsonObject.parse(JSON.stringify(simpleObject), logOrder); 478 return logOrderString; 479 }); 480 result.push(function(jsonObject){ 481 logOrderString = ""; 482 jsonObject.parse(JSON.stringify(complexObject), logOrder); 483 return logOrderString; 484 }); 485 var callCount = 0; 486 function throwAfterFifthCall(key, value) { 487 logOrder(key, value); 488 if (++callCount > 5) 489 throw "from reviver"; 490 return null; 491 } 492 result.push(function(jsonObject){ 493 callCount = 0; 494 logOrderString = ""; 495 return jsonObject.parse(JSON.stringify(complexArray), throwAfterFifthCall); 496 }); 497 result[result.length - 1].throws = true; 498 result.push(function(jsonObject){ 499 callCount = 0; 500 logOrderString = ""; 501 return jsonObject.parse(JSON.stringify(simpleObject), throwAfterFifthCall); 502 }); 503 result.push(function(jsonObject){ 504 callCount = 0; 505 logOrderString = ""; 506 return jsonObject.parse(JSON.stringify(complexObject), throwAfterFifthCall); 507 }); 508 result[result.length - 1].throws = true; 509 result.push(function(jsonObject){ 510 callCount = 0; 511 logOrderString = ""; 512 try { jsonObject.parse(JSON.stringify(complexArray), throwAfterFifthCall); } catch (e) {} 513 return logOrderString; 514 }); 515 result.push(function(jsonObject){ 516 callCount = 0; 517 logOrderString = ""; 518 try { jsonObject.parse(JSON.stringify(simpleObject), throwAfterFifthCall); } catch (e) {} 519 return logOrderString; 520 }); 521 result.push(function(jsonObject){ 522 callCount = 0; 523 logOrderString = ""; 524 try { jsonObject.parse(JSON.stringify(complexObject), throwAfterFifthCall); } catch (e) {} 525 return logOrderString; 526 }); 527 358 528 return result; 359 529 }
Note: See TracChangeset
for help on using the changeset viewer.